home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / pascal / xlibpas2.zip / XBM2.ASM < prev    next >
Assembly Source File  |  1994-06-13  |  91KB  |  2,861 lines

  1. ; ***************************************************************************
  2. ; **                             XLibPas v2.0                              **
  3. ; **                        for Borland Pascal 7.0                         **
  4. ; **                                  by                                   **
  5. ; **                            Tristan Tarrant                            **
  6. ; ***************************************************************************
  7. ; ** Credits :                                                             **
  8. ; **   Michael Abrash    - Concepts, Algorithms                            **
  9. ; **   Themie Gouthas    - Main code and implementation                    **
  10. ; **   Matthew MacKenzie - Compiled Bitmaps, Circles, etc.                 **
  11. ; **   Tore Bastiansen   - Virtual VSync Handler                           **
  12. ; ***************************************************************************
  13.  
  14.         .MODEL TPASCAL
  15.         .386
  16.         LOCALS
  17.  
  18. include xlib2.inc
  19. include xbm2.inc
  20.  
  21.         .CODE
  22.  
  23. xpbmtobm proc far srcpbm:dword,destbm:dword
  24.  
  25.     push ds
  26.     push di
  27.     push si
  28.  
  29.     les  di,[destbm]        ; es:di -> destination bitmap
  30.     lds  si,[srcpbm]        ; ds:si -> source planar bitmap
  31.     lodsb                 ; load AL with source pbm pixel width per plane
  32.     mov  bl,al            ; save in CL
  33.     xor  ah,ah            ; convert to word
  34.     shl  ax,2             ; mult by 4 giving source image width
  35.     cmp  ax,255           ; if the result > 255 then we have exceeded
  36.     ja   @@WidthError     ; the max width of linear bm.
  37.  
  38.     stosb                 ; write do destbm
  39.  
  40.     lodsb                 ; tranfer source pbm height in pixels to
  41.     stosb                           ;  destbm
  42.  
  43.     xor  ah,ah            ; convert to word
  44.     mul  bl               ; AX = AX * BL ie. total no. pixels per plane
  45.     mov  dx,di            ; save DI, the pointer to the destination bm
  46.     mov  bl,3             ; set plane loop counter (BL)
  47.  
  48. @@PlaneLoop:
  49.     mov  cx,ax            ; set CX to total number of pixels per plane
  50.  
  51. @@PixelLoop:
  52.     movsb                 ; transfer pixel
  53.     add  di,3             ; increment destination to compensate for plane
  54.     loop @@PixelLoop
  55.  
  56.     inc  dx               ; increment original di for next pixel plane
  57.     mov  di,dx            ; and restore di from incremented original
  58.     dec  bl               ; decrement plane counter
  59.     jns  @@PlaneLoop      ; loop if more planes left
  60.     xor  ax,ax
  61.     jmp  short @@Done
  62. @@WidthError:
  63.     mov  ax,1
  64.  
  65. @@Done:
  66.     pop  si
  67.     pop  di
  68.     pop  ds
  69.     ret
  70. xpbmtobm endp
  71.  
  72.  
  73. xbmtopbm proc far srcbm:dword,destpbm:dword
  74.     push ds
  75.     push di
  76.     push si
  77.  
  78.     les  di,[destpbm]        ; es:di -> destination planar bitmap
  79.     lds  si,[srcbm]          ; ds:si -> source bitmap
  80.     lodsb                    ; load AX with source bitmap width
  81.     test al,03h              ; Check that width is a multiple of 4
  82.     jnz  @@WidthIncompatible
  83.     shr  al,2                ; divide by 4 giving width of plane
  84.     stosb                    ; store destination planar bitmap width
  85.     mov  bl,al               ;  and copy to bl
  86.     lodsb
  87.     stosb                    ; Transfer source bitmap height to dest pbm
  88.     xor  ah,ah               ; Conver height to word
  89.     mul  bl                  ; calculate the total no. of pixels / plane
  90.     mov  dx,si               ; save source offset
  91.     mov  bl,3
  92.  
  93. @@PlaneLoop:
  94.     mov  cx,ax               ; set CX to total number of pixels per plane
  95.  
  96. @@PixelLoop:
  97.     movsb                    ; transfer pixel
  98.     add  si,3                ; increment src offset to compensate for plane
  99.     loop @@PixelLoop
  100.  
  101.     inc  dx                  ; increment original si for next pixel plane
  102.     mov  si,dx               ; and restore si from incremented original
  103.     dec  bl                  ; decrement plane counter
  104.     jns  @@PlaneLoop         ; loop if more planes left
  105.     xor  ax,ax
  106.     jmp  short @@Done
  107. @@WidthIncompatible:
  108.     mov  ax,1
  109.  
  110. @@Done:
  111.     pop  si
  112.     pop  di
  113.     pop  ds
  114.     ret
  115. xbmtopbm endp
  116.  
  117. xcompilebitmap proc far logicalwidth:word,bitmap:dword,output:dword
  118. LOCAL bwidth,scanx,scany,outputx,outputy,column,setcolumn,inputsize:word
  119.     push si
  120.     push di
  121.     push ds
  122.  
  123.     mov word ptr [scanx],0
  124.     mov word ptr [scany],0
  125.     mov word ptr [outputx],0
  126.     mov word ptr [outputy],0
  127.     mov word ptr [column],0
  128.     mov word ptr [setcolumn],0
  129.  
  130.     lds si,[bitmap]     ; 32-bit pointer to source bitmap
  131.  
  132.     les di,[output]     ; 32-bit pointer to destination stream
  133.  
  134.     lodsb               ; load width byte
  135.     xor ah, ah          ; convert to word
  136.     mov [bwidth], ax    ; save for future reference
  137.     mov bl, al          ; copy width byte to bl
  138.     lodsb               ; load height byte -- already a word since ah=0
  139.     mul bl              ; mult height word by width byte
  140.     mov [inputsize], ax;  to get pixel total
  141.  
  142. @@MainLoop:
  143.     mov bx, [scanx]     ; position in original bitmap
  144.     add bx, [scany]
  145.  
  146.     mov al, [si+bx]     ; get pixel
  147.     or  al, al          ; skip empty pixels
  148.     jnz @@NoAdvance
  149.     jmp @@Advance
  150. @@NoAdvance:
  151.  
  152.     mov dx, [setcolumn]
  153.     cmp dx, [column]
  154.     je @@SameColumn
  155. @@ColumnLoop:
  156.     Emitw ROLAL        ; emit code to move to new column
  157.     Emitw ADCSIIMMED
  158.     Emitb 0
  159.  
  160.     inc dx
  161.     cmp dx, [column]
  162.     jl @@ColumnLoop
  163.  
  164.     Emitb OUTAL        ; emit code to set VGA mask for new column
  165.     mov [setcolumn], dx
  166. @@SameColumn:
  167.     mov dx, [outputy]   ; calculate output position
  168.     add dx, [outputx]
  169.     sub dx, 128
  170.  
  171.     add word ptr [scanx], 4
  172.     mov cx, [scanx]     ; within four pixels of right edge?
  173.     cmp cx, [bwidth]
  174.     jge @@OnePixel
  175.  
  176.     inc word ptr [outputx]
  177.     mov ah, [si+bx+4]   ; get second pixel
  178.     or ah, ah
  179.     jnz @@TwoPixels
  180. @@OnePixel:
  181.     cmp dx, 127         ; can we use shorter form?
  182.     jg @@OnePixLarge
  183.     cmp dx, -128
  184.     jl @@OnePixLarge
  185.     Emitw SHORTSTORE8
  186.     Emitb dl            ; 8-bit position in output
  187.     jmp @@EmitOnePixel
  188. @@OnePixLarge:
  189.     Emitw STORE8
  190.     Emitw dx            ; position in output
  191. @@EmitOnePixel:
  192.     Emitb al
  193.     jmp short @@Advance
  194. @@TwoPixels:
  195.     cmp dx, 127
  196.     jg @@TwoPixLarge
  197.     cmp dx, -128
  198.     jl @@TwoPixLarge
  199.     Emitw SHORTSTORE16
  200.     Emitb dl            ; 8-bit position in output
  201.     jmp @@EmitTwoPixels
  202. @@TwoPixLarge:
  203.     Emitw STORE16
  204.     Emitw dx            ; position in output
  205. @@EmitTwoPixels:
  206.     Emitw ax
  207.  
  208. @@Advance:
  209.     inc word ptr [outputx]
  210.     mov ax, [scanx]
  211.     add ax, 4
  212.     cmp ax, [bwidth]
  213.     jl @@AdvanceDone
  214.     mov dx, [outputy]
  215.     add dx, [logicalwidth]
  216.     mov cx, [scany]
  217.     add cx, [bwidth]
  218.     cmp cx, [inputsize]
  219.     jl @@NoNewColumn
  220.     inc word ptr [column]
  221.     mov cx, [column]
  222.     cmp cx, 4
  223.     je @@Exit           ; Column 4: there is no column 4.
  224.     xor cx, cx          ; scany and outputy are 0 again for
  225.     mov dx, cx          ; the new column
  226. @@NoNewColumn:
  227.     mov [outputy], dx
  228.     mov [scany], cx
  229.     mov word ptr [outputx], 0
  230.     mov ax,[column]
  231. @@AdvanceDone:
  232.     mov [scanx], ax
  233.     jmp @@MainLoop
  234.  
  235. @@Exit:
  236.     Emitb RETURN
  237.     mov ax,di
  238.     sub ax,word ptr [output] ; size of generated code
  239.  
  240.     pop ds
  241.     pop di
  242.     pop si
  243.     ret
  244. xcompilebitmap endp
  245.  
  246.  
  247. xsizeofcbitmap proc far logicalwidth:word,bitmap:dword
  248. LOCAL bwidth,scanx,scany,outputx,outputy,column,setcolumn,inputsize:word
  249.     push si
  250.     push di
  251.     push ds
  252.  
  253.     mov word ptr [scanx], 0
  254.     mov word ptr [scany], 0
  255.     mov word ptr [outputx], 0
  256.     mov word ptr [outputy], 0
  257.     mov word ptr [column], 0
  258.     mov word ptr [setcolumn], 0
  259.  
  260.     lds si,[bitmap]     ; 32-bit pointer to source bitmap
  261.  
  262.     mov di, 1           ; initial size is just the size of the far RET
  263.  
  264.     lodsb               ; load width byte
  265.     xor ah, ah          ; convert to word
  266.     mov [bwidth], ax    ; save for future reference
  267.     mov bl, al          ; copy width byte to bl
  268.     lodsb               ; load height byte -- already a word since ah=0
  269.     mul bl              ; mult height word by width byte
  270.     mov [inputsize], ax;  to get pixel total
  271.  
  272. @@MainLoop:
  273.     mov bx, [scanx]     ; position in original bitmap
  274.     add bx, [scany]
  275.  
  276.     mov al, [si+bx]     ; get pixel
  277.     or  al, al          ; skip empty pixels
  278.     jnz @@NoAdvance
  279.     jmp @@Advance
  280. @@NoAdvance:
  281.  
  282.     mov dx, [setcolumn]
  283.     cmp dx, [column]
  284.     je @@SameColumn
  285. @@ColumnLoop:
  286.     add di, 5           ; size of code to move to new column
  287.     inc dx
  288.     cmp dx,[column]
  289.     jl @@ColumnLoop
  290.  
  291.     inc di              ; size of code to set VGA mask
  292.     mov [setcolumn], dx
  293. @@SameColumn:
  294.     mov dx, [outputy]   ; calculate output position
  295.     add dx, [outputx]
  296.     sub dx, 128
  297.  
  298.     add word ptr [scanx], 4
  299.     mov cx, [scanx]     ; within four pixels of right edge?
  300.     cmp cx, [bwidth]
  301.     jge @@OnePixel
  302.  
  303.     inc word ptr [outputx]
  304.     mov ah,[si+bx+4]    ; get second pixel
  305.     or ah, ah
  306.     jnz @@TwoPixels
  307. @@OnePixel:
  308.     cmp dx, 127         ; can we use shorter form?
  309.     jg @@OnePixLarge
  310.     cmp dx, -128
  311.     jl @@OnePixLarge
  312.     add di, 4           ; size of 8-bit position in output plus one pixel
  313.     jmp @@EmitOnePixel
  314. @@OnePixLarge:
  315.     add di, 5           ; size of position in output plus one pixels
  316. @@EmitOnePixel:
  317.     jmp short @@Advance
  318. @@TwoPixels:
  319.     cmp dx, 127
  320.     jg @@TwoPixLarge
  321.     cmp dx, -128
  322.     jl @@TwoPixLarge
  323.     add di, 5           ; size of 8-bit position in output plus two pixels
  324.     jmp @@EmitTwoPixels
  325. @@TwoPixLarge:
  326.     add di, 6           ; size of 16-bit position in output plus two pixels
  327. @@EmitTwoPixels:
  328.  
  329. @@Advance:
  330.     inc word ptr [outputx]
  331.     mov ax, [scanx]
  332.     add ax,4
  333.     cmp ax, [bwidth]
  334.     jl @@AdvanceDone
  335.     mov dx, [outputy]
  336.     add dx, [logicalwidth]
  337.     mov cx, [scany]
  338.     add cx, [bwidth]
  339.     cmp cx, [inputsize]
  340.     jl @@NoNewColumn
  341.     inc word ptr [column]
  342.     mov cx, [column]
  343.     cmp cx, 4
  344.     je @@Exit           ; Column 4: there is no column 4.
  345.     xor cx,cx           ; scany and outputy are 0 again for
  346.     mov dx,cx           ; the new column
  347. @@NoNewColumn:
  348.     mov [outputy], dx
  349.     mov [scany], cx
  350.     mov word ptr [outputx], 0
  351.     mov ax,[column]
  352. @@AdvanceDone:
  353.     mov [scanx], ax
  354.     jmp @@MainLoop
  355.  
  356. @@Exit:
  357.     mov ax, di          ; size of generated code
  358.  
  359.     pop ds
  360.     pop di
  361.     pop si
  362.     ret
  363. xsizeofcbitmap endp
  364.  
  365. xputcbitmap proc far XPos:word,YPos:word,PageOffset:word,Sprite:dword
  366.  
  367.     push ds
  368.     mov cx, [SelectorInc]
  369.     mov ax, [ScrnLogicalByteWidth] ; global Xlib variable
  370.     mul word ptr [YPos] ; height in bytes
  371.     mov si, [XPos]
  372.     mov bx, si
  373.     sar si, 2           ; width in bytes
  374.     add si, ax
  375.     add si, [PageOffset]; (YPos * screen width) +
  376.     add si, 128         ;   (Xpos / 4) + page base + 128 ==> starting pos
  377.  
  378.     and bx, 3
  379.     mov ah, ColumnMask[bx]
  380.  
  381.     mov dx, SCINDEX
  382.     mov al, MAPMASK
  383.     out dx, ax
  384.     inc dx              ; ready to send out other masks as bytes
  385.     mov al, ah
  386.     mov bx, SCREENSEG
  387.     mov ds, bx          ; We do this so the compiled shape won't need
  388.                                             ; segment overrides.
  389.     call dword ptr [Sprite] ; the business end of the routine
  390.     pop ds
  391.  
  392.     ret
  393. xputcbitmap endp
  394.  
  395.  
  396. xcompilepbm proc far logicalwidth:word,bitmap:dword,output:dword
  397. LOCAL bwidth,scanx,scany,outputx,outputy,column,setcolumn,inputsize:word
  398.     push si
  399.     push di
  400.     push ds
  401.  
  402.     mov word ptr [scanx],0
  403.     mov word ptr [scany],0
  404.     mov word ptr [outputx],0
  405.     mov word ptr [outputy],0
  406.     mov word ptr [column],0
  407.     mov word ptr [setcolumn],0
  408.  
  409.     lds si,[bitmap]     ; 32-bit pointer to source bitmap
  410.  
  411.     les di,[output]     ; 32-bit pointer to destination stream
  412.  
  413.     lodsb               ; load width byte
  414.     xor ah, ah          ; convert to word
  415.     mov [bwidth], ax    ; save for future reference
  416.     mov bl, al          ; copy width byte to bl
  417.     lodsb               ; load height byte -- already a word since ah=0
  418.     mul bl              ; mult height word by width byte
  419.     mov [inputsize], ax;  to get pixel total
  420.  
  421. @@MainLoop:
  422.     mov bx, [scanx]     ; position in original bitmap
  423.     add bx, [scany]
  424.  
  425.     mov al, [si+bx]     ; get pixel
  426.     or  al, al          ; skip empty pixels
  427.     jnz @@NoAdvance
  428.     jmp @@Advance
  429. @@NoAdvance:
  430.  
  431.     mov dx, [setcolumn]
  432.     cmp dx, [column]
  433.     je @@SameColumn
  434. @@ColumnLoop:
  435.     Emitw ROLAL        ; emit code to move to new column
  436.     Emitw ADCSIIMMED
  437.     Emitb 0
  438.  
  439.     inc dx
  440.     cmp dx, [column]
  441.     jl @@ColumnLoop
  442.  
  443.     Emitb OUTAL        ; emit code to set VGA mask for new column
  444.     mov [setcolumn], dx
  445. @@SameColumn:
  446.     mov dx, [outputy]   ; calculate output position
  447.     add dx, [outputx]
  448.     sub dx, 128
  449.  
  450.     inc word ptr [scanx]
  451.     mov cx, [scanx]     ; within four pixels of right edge?
  452.     cmp cx, [bwidth]
  453.     jge @@OnePixel
  454.  
  455.     inc word ptr [outputx]
  456.     mov ah, [si+bx+1]   ; get second pixel
  457.     or ah, ah
  458.     jnz @@TwoPixels
  459. @@OnePixel:
  460.     cmp dx, 127         ; can we use shorter form?
  461.     jg @@OnePixLarge
  462.     cmp dx, -128
  463.     jl @@OnePixLarge
  464.     Emitw SHORTSTORE8
  465.     Emitb dl            ; 8-bit position in output
  466.     jmp @@EmitOnePixel
  467. @@OnePixLarge:
  468.     Emitw STORE8
  469.     Emitw dx            ; position in output
  470. @@EmitOnePixel:
  471.     Emitb al
  472.     jmp short @@Advance
  473. @@TwoPixels:
  474.     cmp dx, 127
  475.     jg @@TwoPixLarge
  476.     cmp dx, -128
  477.     jl @@TwoPixLarge
  478.     Emitw SHORTSTORE16
  479.     Emitb dl            ; 8-bit position in output
  480.     jmp @@EmitTwoPixels
  481. @@TwoPixLarge:
  482.     Emitw STORE16
  483.     Emitw dx            ; position in output
  484. @@EmitTwoPixels:
  485.     Emitw ax
  486.  
  487. @@Advance:
  488.     inc word ptr [outputx]
  489.     mov ax, [scanx]
  490.     inc ax
  491.     cmp ax, [bwidth]
  492.     jl @@AdvanceDone
  493.     mov dx, [outputy]
  494.     add dx, [logicalwidth]
  495.     mov cx, [scany]
  496.     add cx, [bwidth]
  497.     cmp cx, [inputsize]
  498.     jl @@NoNewColumn
  499.     inc word ptr [column]
  500.     mov cx, [column]
  501.     cmp cx, 4
  502.     je @@Exit           ; Column 4: there is no column 4.
  503.     xor cx, cx          ; scany and outputy are 0 again for
  504.     mov dx, cx          ; the new column
  505.     add si, [inputsize]
  506. @@NoNewColumn:
  507.     mov [outputy], dx
  508.     mov [scany], cx
  509.     xor ax, ax
  510.     mov word ptr [outputx], 0
  511. @@AdvanceDone:
  512.     mov [scanx], ax
  513.     jmp @@MainLoop
  514.  
  515. @@Exit:
  516.     Emitb RETURN
  517.     mov ax,di
  518.     sub ax,word ptr [output] ; size of generated code
  519.  
  520.     pop ds
  521.     pop di
  522.     pop si
  523.     ret
  524. xcompilepbm endp
  525.  
  526.  
  527. xsizeofcpbm proc far logicalwidth:word,bitmap:dword
  528. LOCAL bwidth,scanx,scany,outputx,outputy,column,setcolumn,inputsize:word
  529.     push si
  530.     push di
  531.     push ds
  532.  
  533.     mov word ptr [scanx], 0
  534.     mov word ptr [scany], 0
  535.     mov word ptr [outputx], 0
  536.     mov word ptr [outputy], 0
  537.     mov word ptr [column], 0
  538.     mov word ptr [setcolumn], 0
  539.  
  540.     lds si,[bitmap]     ; 32-bit pointer to source bitmap
  541.  
  542.     mov di, 1           ; initial size is just the size of the far RET
  543.  
  544.     lodsb               ; load width byte
  545.     xor ah, ah          ; convert to word
  546.     mov [bwidth], ax    ; save for future reference
  547.     mov bl, al          ; copy width byte to bl
  548.     lodsb               ; load height byte -- already a word since ah=0
  549.     mul bl              ; mult height word by width byte
  550.     mov [inputsize], ax;  to get pixel total
  551.  
  552. @@MainLoop:
  553.     mov bx, [scanx]     ; position in original bitmap
  554.     add bx, [scany]
  555.  
  556.     mov al, [si+bx]     ; get pixel
  557.     or  al, al          ; skip empty pixels
  558.     jnz @@NoAdvance
  559.     jmp @@Advance
  560. @@NoAdvance:
  561.  
  562.     mov dx, [setcolumn]
  563.     cmp dx, [column]
  564.     je @@SameColumn
  565. @@ColumnLoop:
  566.     add di, 5           ; size of code to move to new column
  567.     inc dx
  568.     cmp dx,[column]
  569.     jl @@ColumnLoop
  570.  
  571.     inc di              ; size of code to set VGA mask
  572.     mov [setcolumn], dx
  573. @@SameColumn:
  574.     mov dx, [outputy]   ; calculate output position
  575.     add dx, [outputx]
  576.     sub dx, 128
  577.  
  578.     inc word ptr [scanx]
  579.     mov cx, [scanx]     ; within four pixels of right edge?
  580.     cmp cx, [bwidth]
  581.     jge @@OnePixel
  582.  
  583.     inc word ptr [outputx]
  584.     mov ah,[si+bx+1]    ; get second pixel
  585.     or ah, ah
  586.     jnz @@TwoPixels
  587. @@OnePixel:
  588.     cmp dx, 127         ; can we use shorter form?
  589.     jg @@OnePixLarge
  590.     cmp dx, -128
  591.     jl @@OnePixLarge
  592.     add di, 4           ; size of 8-bit position in output plus one pixel
  593.     jmp @@EmitOnePixel
  594. @@OnePixLarge:
  595.     add di, 5           ; size of position in output plus one pixels
  596. @@EmitOnePixel:
  597.     jmp short @@Advance
  598. @@TwoPixels:
  599.     cmp dx, 127
  600.     jg @@TwoPixLarge
  601.     cmp dx, -128
  602.     jl @@TwoPixLarge
  603.     add di, 5           ; size of 8-bit position in output plus two pixels
  604.     jmp @@EmitTwoPixels
  605. @@TwoPixLarge:
  606.     add di, 6           ; size of 16-bit position in output plus two pixels
  607. @@EmitTwoPixels:
  608.  
  609. @@Advance:
  610.     inc word ptr [outputx]
  611.     mov ax, [scanx]
  612.     inc ax
  613.     cmp ax, [bwidth]
  614.     jl @@AdvanceDone
  615.     mov dx, [outputy]
  616.     add dx, [logicalwidth]
  617.     mov cx, [scany]
  618.     add cx, [bwidth]
  619.     cmp cx, [inputsize]
  620.     jl @@NoNewColumn
  621.     inc word ptr [column]
  622.     mov cx, [column]
  623.     cmp cx, 4
  624.     je @@Exit           ; Column 4: there is no column 4.
  625.     xor cx,cx           ; scany and outputy are 0 again for
  626.     mov dx,cx           ; the new column
  627.     add si, [inputsize]
  628. @@NoNewColumn:
  629.     mov [outputy], dx
  630.     mov [scany], cx
  631.     xor ax, ax
  632.     mov word ptr [outputx], ax
  633. @@AdvanceDone:
  634.     mov [scanx], ax
  635.     jmp @@MainLoop
  636.  
  637. @@Exit:
  638.     mov ax, di          ; size of generated code
  639.  
  640.     pop ds
  641.     pop di
  642.     pop si
  643.     ret
  644. xsizeofcpbm endp
  645.  
  646. xflipmaskedpbm  proc far X:word,Y:word,ScrnOffs:word,Bitmap:dword,Orientation:word
  647. LOCAL Plane:byte,BMHeight:byte,LineInc:word
  648.  
  649.     push  si
  650.     push  di
  651.     push  ds
  652.     cld
  653.     mov   ax,SCREENSEG
  654.     mov   es,ax
  655.     mov   ax,[Y]                      ; Calculate dest screen row
  656.     mov   bx,[ScrnLogicalByteWidth]  ;  by mult. dest Y coord by Screen
  657.     mul   bx                          ;  width then adding screen offset
  658.     mov   di,[ScrnOffs]               ;  store result in DI
  659.     add   di,ax
  660.     mov   cx,[X]                      ; Load X coord into CX and make a
  661.     mov   dx,cx                       ;  copy in DX
  662.     shr   dx,2                        ; Find starting byte in dest row
  663.     add   di,dx                       ;  add to DI giving screen offset of
  664.                                                                                     ;  first pixel's byte
  665.     lds   si,[Bitmap]                 ; DS:SI -> Bitmap data
  666.     lodsw                             ; Al = B.M. width (bytes) AH = B.M.
  667.                                                                                     ;  height
  668.     cmp   Orientation,0
  669.     jz    UnFlippedMasked
  670.  
  671.     mov   [BMHeight],ah               ; Save source bitmap dimensions
  672.                 xor   ah,ah                       ; LineInc = bytes to the begin.
  673.     add   bx,ax                       ;  of bitmaps next row on screen
  674.     mov   [LineInc],bx
  675.     mov   bh,al                       ; Use bh as column loop count
  676.                 and   cx,0003h                    ; mask X coord giving plane of 1st
  677.                         ; bitmap pixel(zero CH coincidentally)
  678.     mov   ah,11h                      ; Init. mask for VGA plane selection
  679.     shl   ah,cl                       ; Shift for starting pixel plane
  680.     mov   dx,SCINDEX                 ; Prepare VGA for cpu to video writes
  681.     mov   al,MAPMASK
  682.     out   dx,al
  683.     inc   dx
  684.     mov   [Plane],4                   ; Set plane counter to 4
  685. @@PlaneLoop:
  686.     push  di                          ; Save bitmap's start dest. offset
  687.     mov   bl,[BMHeight]               ; Reset row counter (BL)
  688.     mov   al,ah
  689.     out   dx,al                       ; set vga write plane
  690. @@RowLoop:
  691.     mov   cl,bh                       ; Reset Column counter cl
  692. @@ColLoop:
  693.     lodsb                             ; Get next source bitmap byte
  694.     or    al,al                       ; If not zero then write to dest.
  695.     jz    @@NoPixel                   ; otherwise skip to next byte
  696.     mov   es:[di],al
  697. @@NoPixel:
  698.     dec   di
  699.     loop  @@ColLoop                   ; loop if more columns left
  700.     add   di,[LineInc]                ; Move to next row
  701.     dec   bl                          ; decrement row counter
  702.     jnz   @@RowLoop                   ; Jump if more rows left
  703.     pop   di                          ; Restore bitmaps start dest byte
  704.     ror   ah,1                        ; Shift mask for next plane
  705.     sbb   di,0                        ; If wrapped increment dest address
  706.     dec   [Plane]                     ; Decrement plane counter
  707.     jnz   @@PlaneLoop                 ; Jump if more planes left
  708.  
  709.     pop   ds                          ; restore data segment
  710.     pop   di                          ; restore registers
  711.     pop   si
  712.     ret
  713. xflipmaskedpbm  endp
  714.  
  715.  
  716. xputmaskedpbm  proc far X:word,Y:word,ScrnOffs:word,Bitmap:dword
  717. LOCAL Plane:byte,BMHeight:byte,LineInc:word
  718.     push  si
  719.     push  di
  720.     push  ds
  721.     cld
  722.     mov   ax,SCREENSEG
  723.     mov   es,ax
  724.     mov   ax,Y                      ; Calculate dest screen row
  725.     mov   bx,ScrnLogicalByteWidth  ;  by mult. dest Y coord by Screen
  726.     mul   bx                          ;  width then adding screen offset
  727.     mov   di,[ScrnOffs]               ;  store result in DI
  728.     add   di,ax
  729.     mov   cx,[X]                      ; Load X coord into CX and make a
  730.     mov   dx,cx                       ;  copy in DX
  731.     shr   dx,2                        ; Find starting byte in dest row
  732.     add   di,dx                       ;  add to DI giving screen offset of
  733.                                                                                     ;  first pixel's byte
  734.     lds   si,[Bitmap]                 ; DS:SI -> Bitmap data
  735.     lodsw                             ; Al = B.M. width (bytes) AH = B.M.
  736.                                                                                     ;  height
  737. UnFlippedMasked:
  738.     mov   [BMHeight],ah               ; Save source bitmap dimensions
  739.     xor   ah,ah                       ; LineInc = bytes to the begin.
  740.     sub   bx,ax                       ;  of bitmaps next row on screen
  741.     mov   [LineInc],bx
  742.     mov   bh,al                       ; Use bh as column loop count
  743.     and   cx,0003h                    ; mask X coord giving plane of 1st
  744.                                                                         ; bitmap pixel(zero CH coincidentally)
  745.     mov   ah,11h                      ; Init. mask for VGA plane selection
  746.     shl   ah,cl                       ; Shift for starting pixel plane
  747.     mov   dx,SCINDEX                 ; Prepare VGA for cpu to video writes
  748.     mov   al,MAPMASK
  749.     out   dx,al
  750.     inc   dx
  751.     mov   [Plane],4                   ; Set plane counter to 4
  752. @@PlaneLoop:
  753.     push  di                          ; Save bitmap's start dest. offset
  754.     mov   bl,[BMHeight]               ; Reset row counter (BL)
  755.     mov   al,ah
  756.     out   dx,al                       ; set vga write plane
  757. @@RowLoop:
  758.     mov   cl,bh                       ; Reset Column counter cl
  759. @@ColLoop:
  760.     lodsb                             ; Get next source bitmap byte
  761.     or    al,al                       ; If not zero then write to dest.
  762.     jz    @@NoPixel                   ; otherwise skip to next byte
  763.     mov   es:[di],al
  764. @@NoPixel:
  765.     inc   di
  766.     loop  @@ColLoop                   ; loop if more columns left
  767.     add   di,[LineInc]                ; Move to next row
  768.     dec   bl                          ; decrement row counter
  769.     jnz   @@RowLoop                   ; Jump if more rows left
  770.     pop   di                          ; Restore bitmaps start dest byte
  771.     rol   ah,1                        ; Shift mask for next plane
  772.     adc   di,0                        ; If wrapped increment dest address
  773.     dec   [Plane]                     ; Decrement plane counter
  774.     jnz   @@PlaneLoop                 ; Jump if more planes left
  775.  
  776.     pop   ds                          ; restore data segment
  777.     pop   di                          ; restore registers
  778.     pop   si
  779.     ret
  780. xputmaskedpbm  endp
  781.  
  782. xputpbm  proc far X:word,Y:word,ScrnOffs:word,Bitmap:dword
  783. LOCAL Plane:byte,BMHeight:byte,LineInc:word
  784.     push  si
  785.     push  di
  786.     push  ds
  787.     cld
  788.     mov   ax,SCREENSEG
  789.     mov   es,ax
  790.     mov   ax,[Y]                      ; Calculate dest screen row
  791.     mov   bx,[ScrnLogicalByteWidth]  ;  by mult. dest Y coord by Screen
  792.     mul   bx                          ;  width then adding screen offset
  793.     mov   di,[ScrnOffs]               ;  store result in DI
  794.     add   di,ax
  795.     mov   cx,[X]                      ; Load X coord into CX and make a
  796.     mov   dx,cx                       ;  copy in DX
  797.     shr   dx,2                        ; Find starting byte in dest row
  798.     add   di,dx                       ;  add to DI giving screen offset of
  799.                                                                                     ;  first pixel's byte
  800.     lds   si,[Bitmap]                 ; DS:SI -> Bitmap data
  801.     lodsw                             ; Al = B.M. width (bytes) AH = B.M.
  802.                                                                                     ;  height
  803. UnFlipped:
  804.     mov   [BMHeight],ah               ; Save source bitmap dimensions
  805.     xor   ah,ah                       ; LineInc = bytes to the begin.
  806.     sub   bx,ax                       ;  of bitmaps next row on screen
  807.     mov   [LineInc],bx
  808.     mov   bh,al
  809.                                                                         ; Self Modifying, Shame, shame shame..
  810.     and   cx,0003h                    ; mask X coord giving plane of 1st
  811.                                                                         ; bitmap pixel(zero CH coincidentally)
  812.     mov   ah,11h                      ; Init. mask for VGA plane selection
  813.     shl   ah,cl                       ; Shift for starting pixel plane
  814.     mov   dx,SCINDEX                 ; Prepare VGA for cpu to video writes
  815.     mov   al,MAPMASK
  816.     out   dx,al
  817.     inc   dx
  818.     mov   [Plane],4                   ; Set plane counter to 4
  819. @@PlaneLoop:
  820.     push  di
  821.     mov   bl,[BMHeight]
  822.     mov   al,ah
  823.     out   dx,al
  824. @@RowLoop:
  825.     mov   cl,bh
  826.     shr   cl,1
  827.     rep   movsw                       ; Copy a complete row for curr plane
  828.     adc   cl,0
  829.     rep   movsb
  830.     add   di,[LineInc]                ; Move to next row
  831.     dec   bl                          ; decrement row counter
  832.     jnz   @@RowLoop                   ; Jump if more rows left
  833.     pop   di                          ; Restore bitmaps start dest byte
  834.     rol   ah,1                        ; Shift mask for next plane
  835.     adc   di,0                        ; If wrapped increment dest address
  836.     dec   [Plane]                     ; Decrement plane counter
  837.     jnz   @@PlaneLoop                 ; Jump if more planes left
  838.  
  839.     pop   ds                          ; restore data segment
  840.     pop   di                          ; restore registers
  841.     pop   si
  842.     ret
  843. xputpbm  endp
  844.  
  845. xflippbm  proc far X:word,Y:word,ScrnOffs:word,Bitmap:dword,Orientation:word
  846. LOCAL Plane:byte,BMHeight:byte,LineInc:word
  847.     push  si
  848.     push  di
  849.     push  ds
  850.     cld
  851.     mov   ax,SCREENSEG
  852.     mov   es,ax
  853.     mov   ax,[Y]                      ; Calculate dest screen row
  854.     mov   bx,[ScrnLogicalByteWidth]   ;  by mult. dest Y coord by Screen
  855.     mul   bx                          ;  width then adding screen offset
  856.     mov   di,[ScrnOffs]               ;  store result in DI
  857.     add   di,ax
  858.     mov   cx,[X]                      ; Load X coord into CX and make a
  859.     mov   dx,cx                       ;  copy in DX
  860.     shr   dx,2                        ; Find starting byte in dest row
  861.     add   di,dx                       ;  add to DI giving screen offset of
  862.                                                                                     ;  first pixel's byte
  863.     lds   si,[Bitmap]                 ; DS:SI -> Bitmap data
  864.     lodsw                             ; Al = B.M. width (bytes) AH = B.M.
  865.                                                                                     ;  height
  866.     cmp   Orientation,0
  867.     jz    UnFlipped
  868.  
  869.     mov   [BMHeight],ah               ; Save source bitmap dimensions
  870.                 xor   ah,ah                       ; LineInc = bytes to the begin.
  871.     add   bx,ax                       ;  of bitmaps next row on screen
  872.     mov   [LineInc],bx
  873.     mov   bh,al                       ; Use bh as column loop count
  874.                 and   cx,0003h              ; mask X coord giving plane of 1st
  875.                                                                         ; bitmap pixel(zero CH coincidentally)
  876.     mov   ah,11h                      ; Init. mask for VGA plane selection
  877.     shl   ah,cl                       ; Shift for starting pixel plane
  878.     mov   dx,SCINDEX                  ; Prepare VGA for cpu to video writes
  879.     mov   al,MAPMASK
  880.     out   dx,al
  881.     inc   dx
  882.     mov   [Plane],4                   ; Set plane counter to 4
  883. @@PlaneLoop:
  884.     push  di                          ; Save bitmap's start dest. offset
  885.     mov   bl,[BMHeight]               ; Reset row counter (BL)
  886.     mov   al,ah
  887.     out   dx,al                       ; set vga write plane
  888. @@RowLoop:
  889.     mov   cl,bh                       ; Reset Column counter cl
  890. @@ColLoop:
  891.     lodsb
  892.     mov   es:[di],al
  893.     dec   di
  894.     sub   di,2
  895.     loop  @@ColLoop                   ; loop if more columns left
  896. @@DoneCol:
  897.     add   di,[LineInc]                ; Move to next row
  898.     dec   bl                          ; decrement row counter
  899.     jnz   @@RowLoop                   ; Jump if more rows left
  900.     pop   di                          ; Restore bitmaps start dest byte
  901.     ror   ah,1                        ; Shift mask for next plane
  902.     sbb   di,0                        ; If wrapped increment dest address
  903.     dec   [Plane]                     ; Decrement plane counter
  904.     jnz   @@PlaneLoop                 ; Jump if more planes left
  905.     pop   ds                          ; restore data segment
  906.     pop   di                          ; restore registers
  907.     pop   si
  908.     ret
  909.  
  910. xflippbm  endp
  911.  
  912. xgetpbm  proc far X:word,Y:word,SrcWidth:byte,SrcHeight:byte,ScrnOffs:word,Bitmap:dword
  913. LOCAL Plane:byte,LineInc:word
  914.     push  si
  915.     push  di
  916.     push  ds
  917.     cld
  918.  
  919.     mov   ax,[Y]                      ; Calculate screen row
  920.     mov   bx,[ScrnLogicalByteWidth]   ;  by mult. Y coord by Screen
  921.     mul   bx                          ;  width then adding screen offset
  922.     mov   si,[ScrnOffs]               ;  store result in SI
  923.     add   si,ax
  924.     mov   cx,[X]                      ; Load X coord into CX and make a
  925.     mov   dx,cx                       ;  copy in DX
  926.     shr   dx,2                        ; Find starting byte in screen row
  927.     add   si,dx                       ;  add to SI giving screen offset of
  928.                                                                         ;  first pixel's byte
  929.     mov   ax,SCREENSEG
  930.     mov   ds,ax
  931.     les   di,[Bitmap]                 ; ES:DI -> Bitmap data
  932.     mov   al,[SrcWidth]
  933.     mov   ah,[SrcHeight]
  934.     stosw                             ; Al = B.M. width (bytes) AH = B.M.
  935.                                                                         ;  height
  936.     xor   ah,ah                                             ; LineInc = bytes to the begin.
  937.     sub   bx,ax                       ;  of bitmaps next row on screen
  938.     mov   [LineInc],bx
  939.     mov   bh,al
  940.                                                                         ; Self Modifying, Shame, shame shame..
  941.     and   cx,0003h                    ; mask X coord giving plane of 1st
  942.                                                                         ; bitmap pixel(zero CH coincidentally)
  943.     mov   ah,11h                      ; Init. mask for VGA plane selection
  944.     shl   ah,cl                       ; Shift for starting pixel plane
  945.     mov   dx,GCINDEX                  ; Prepare VGA for cpu to video reads
  946.     mov   al,READMAP
  947.     out   dx,al
  948.     inc   dx
  949.     mov   [Plane],4                   ; Set plane counter (BH) to 4
  950.     mov   al,cl
  951. @@PlaneLoop:
  952.     push  si
  953.     mov   bl,[SrcHeight]
  954.     out   dx,al
  955. @@RowLoop:
  956.     mov   cl,bh
  957.     shr   cl,1
  958.     rep   movsw                       ; Copy a complete row for curr plane
  959.     adc   cl,0
  960.     rep   movsb
  961.     add   si,[LineInc]                ; Move to next row
  962.     dec   bl                          ; decrement row counter
  963.     jnz   @@RowLoop                   ; Jump if more rows left
  964.     pop   si                          ; Restore bitmaps start dest byte
  965.  
  966.     inc   al                          ; Select next plane to read from
  967.     and   al,3                        ;
  968.  
  969.     rol   ah,1                        ; Shift mask for next plane
  970.     adc   si,0                        ; If wrapped increment dest address
  971.     dec   [Plane]                     ; Decrement plane counter
  972.     jnz   @@PlaneLoop                 ; Jump if more planes left
  973.  
  974.     pop   ds                          ; restore data segment
  975.     pop   di                          ; restore registers
  976.     pop   si
  977.     ret
  978. xgetpbm  endp
  979.  
  980. xputmaskedpbmclipx  proc far X:word,Y:word,ScrnOffs:word,Bitmap:dword
  981. LOCAL   Plane:byte,CType,LeftSkip,DataInc,AWidth,Height,TopRow,LineInc:word
  982.     push  si
  983.     push  di
  984.     push  ds
  985.     cld
  986.  
  987.     les   si,[Bitmap]                 ; Point ES:SI to start of bitmap
  988.  
  989.     xor   ax,ax                       ; Clear AX
  990.     mov   [CType],ax                  ; Clear Clip type descision var
  991.     mov   al,byte ptr es:[si]         ; AX=width (byte coverted to word)
  992.  
  993.  
  994.     mov   di,[X]                      ; DI = X coordinate of dest
  995.     mov   cx,di                       ; copy to CX
  996.     sar   di,2                        ; convert to offset in row
  997.     mov   dx,[LeftClip]               ; Is X Coord to the right of
  998.     sub   dx,di                       ; LeftClip ?
  999.     jle   @@NotLeftClip               ; Yes! => no left clipping
  1000.     cmp   dx,ax                       ; Is dist of X Coord from
  1001.     jnl   @@NotVisible                ; ClipLeft > Width ? yes => the
  1002.                         ; bitmap is not visible
  1003.     add   di,dx
  1004.     mov   [LeftSkip],dx
  1005.     mov   [DataInc],dx
  1006.     sub   ax,dx
  1007.     mov   [CType],1
  1008.     jmp   short @@HorizClipDone
  1009.  
  1010. @@NotVisible:
  1011.     mov   ax,1
  1012.     pop   ds                          ; restore data segment
  1013.     pop   di
  1014.     pop   si
  1015.     ret
  1016.  
  1017. @@NotLeftClip:
  1018.     mov   dx,[RightClip]
  1019.     sub   dx,di
  1020.     js    @@NotVisible
  1021.     mov   [LeftSkip],0
  1022.     mov   [DataInc],0
  1023.     cmp   dx,ax
  1024.     jge   @@HorizClipDone
  1025.     inc   dx
  1026.     sub   ax,dx
  1027.     mov   [DataInc],ax
  1028.     mov   ax,dx
  1029.     mov   [CType],-1
  1030.  
  1031. @@HorizClipDone:
  1032.  
  1033.     xor   bh,bh
  1034.     mov   bl,byte ptr es:[si+1]
  1035.  
  1036.     mov   [AWidth],ax
  1037.     mov   [Height],bx
  1038.  
  1039.  
  1040.     add   si,2
  1041.     add   si,[LeftSkip]
  1042.     mov   bx,[ScrnLogicalByteWidth]
  1043.     mov   dx,bx
  1044.     sub   dx,ax
  1045.     mov   [LineInc],dx
  1046.  
  1047.     mov   ax,[Y]
  1048.     mul   bx
  1049.     add   di,ax
  1050.     add   di,[ScrnOffs]
  1051.     mov   ax,es
  1052.     mov   ds,ax
  1053.     mov   ax,SCREENSEG
  1054.     mov   es,ax
  1055.  
  1056.     and   cx,3
  1057.     mov   ah,11h
  1058.     shl   ah,cl
  1059.  
  1060.     mov   dx,SCINDEX
  1061.     mov   al,MAPMASK
  1062.     out   dx,al
  1063.     inc   dx
  1064.     mov   [Plane],4
  1065.     mov   bh,byte ptr [AWidth]
  1066. @@PlaneLoop:
  1067.     push  di
  1068.     mov   bl,byte ptr [Height]
  1069.     mov   al,ah
  1070.     out   dx,al
  1071. @@RowLoop:
  1072.     mov   cl,bh
  1073.     jcxz  @@NoWidth
  1074. @@ColLoop:
  1075.     lodsb
  1076.     or    al,al
  1077.     jz    @@NoPixel
  1078.     mov   es:[di],al
  1079. @@NoPixel:
  1080.     inc   di
  1081.     loop @@ColLoop
  1082. @@NoWidth:
  1083.     add   si,[DataInc]
  1084.     add   di,[LineInc]
  1085.     dec   bl
  1086.     jnz   @@RowLoop
  1087.     pop   di
  1088.     rol   ah,1
  1089.  
  1090.     jnb   @@Nocarry                   ; Jump if not plane transition
  1091.     mov   bl,ah                       ; Save Plane Mask
  1092.     mov   ax,[CType]                  ; set AX to clip type inc variable
  1093.     add   bh,al                       ; Update advancing variables
  1094.     sub   [DataInc],ax                ;
  1095.     sub   [LineInc],ax                ;
  1096.     cmp   al,0                        ; What type of clip do we have
  1097.     mov   ah,bl                       ;   restore Plane mask
  1098.     jg    @@RightAdvance              ; jump on a right clip!
  1099.     inc   di                          ; otherwise increment DI
  1100.     jmp   @@Nocarry
  1101. @@RightAdvance:
  1102.     dec si
  1103. @@Nocarry:
  1104.     dec   [Plane]                     ; Decrement plane counter
  1105.     jnz   @@PlaneLoop                 ; Jump if more planes left
  1106.  
  1107.     xor   ax,ax
  1108.     pop   ds                          ; restore data segment
  1109.     pop   di                          ; restore registers
  1110.     pop   si
  1111.     ret
  1112. xputmaskedpbmclipx  endp
  1113.  
  1114. xputmaskedpbmclipy  proc far X:word,Y:word,ScrnOffs:word,Bitmap:dword
  1115. LOCAL   AWidth,Height,TopRow,LineInc,PlaneInc:word
  1116.     push  si
  1117.     push  di
  1118.     push  ds
  1119.     cld
  1120.  
  1121.     les   si,[Bitmap]
  1122.  
  1123.     xor   bh,bh
  1124.     mov   bl,byte ptr es:[si+1]       ; BX = height
  1125.  
  1126.     xor   ah,ah
  1127.     mov   al,byte ptr es:[si]         ; AX = width
  1128.  
  1129.     mov   cx,ax                       ; Save AX
  1130.     mul   bx                          ; AX = AX*BX = bytes/plane
  1131.     mov   [PlaneInc],ax               ;  save as PlaneInc
  1132.     mov   ax,cx                       ; Restore AX
  1133.  
  1134.     mov   di,[X]
  1135.     mov   cx,di
  1136.     shr   di,2
  1137.  
  1138.     ;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;;
  1139.  
  1140.     mov   dx,[TopClip]           ; Compare u.l. Y coord with Top
  1141.     sub   dx,[Y]                  ; clipping border
  1142.     jle   @@NotTopClip            ; jump if VBM not clipped from above
  1143.     cmp   dx,bx
  1144.     jnl   @@NotVisible            ; jump if VBM is completely obscured
  1145.     mov   [TopRow],dx
  1146.     sub   bx,dx
  1147.     add   [Y],dx
  1148.     jmp   short @@VertClipDone
  1149.  
  1150.     ;;;; EXIT FOR COMPLETELY OBSCURED P.B.M's ;;;;;;;;;;;;;;;;;;;;;;
  1151.  
  1152. @@NotVisible:
  1153.     mov   ax,1
  1154.     pop   ds                          ; restore data segment
  1155.     pop   di                          ; restore registers
  1156.     pop   si
  1157.     ret
  1158.  
  1159.     ;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;;
  1160.  
  1161. @@NotTopClip:
  1162.     mov   dx,[BottomClip]
  1163.     sub   dx,[Y]
  1164.     js    @@NotVisible
  1165.     mov   [TopRow],0
  1166.     cmp   dx,bx
  1167.     jg    @@VertClipDone
  1168.     inc   dx
  1169.     mov   bx,dx
  1170.  
  1171. @@VertClipDone:
  1172.  
  1173.     mov   [AWidth],ax
  1174.     mov   [Height],bx                 ; Calculate relative offset in data
  1175.     mul   [TopRow]                    ;  of first visible scanline
  1176.     add   ax,2                        ; Skip dimension bytes in source
  1177.     add   si,ax                       ; Skip top rows that arent visible
  1178.  
  1179.  
  1180.     mov   ax,[Y]                      ; Calculate screen row
  1181.     mov   bx,[ScrnLogicalByteWidth]  ;  by mult. Y coord by Screen
  1182.     mul   bx                          ;  width then adding screen offset
  1183.     add   di,ax
  1184.     add   di,[ScrnOffs]
  1185.     sub   bx,[AWidth]                  ; calculate difference from end of
  1186.     mov   [LineInc],bx                ; b.m. in curr line to beginning of
  1187.                         ; b.m. on next scan line
  1188.     mov   ax,es                       ; copy ES to DS
  1189.     mov   ds,ax
  1190.     mov   ax,SCREENSEG               ; Point ES to VGA segment
  1191.     mov   es,ax
  1192.  
  1193.     mov   ah,11h                      ; Set up initial plane mask
  1194.     and   cx,3
  1195.     shl   ah,cl
  1196.  
  1197.     mov   dx,SCINDEX                 ; Prepare VGA for cpu to video writes
  1198.     mov   al,MAPMASK
  1199.     out   dx,al
  1200.     inc   dx
  1201.     mov   bh,4                        ; Set plane counter to 4
  1202. @@PlaneLoop:
  1203.     push  di        ; Save bitmap's start dest. offset
  1204.     push  si                          ; Save Bitmaps data offset
  1205.     mov   bl,byte ptr [Height]        ; Reset row counter (BL)
  1206.     mov   al,ah
  1207.     out   dx,al                       ; set vga write plane
  1208. @@RowLoop:
  1209.     mov   cl,byte ptr [AWidth]         ; Reset Column counter cl
  1210. @@ColLoop:
  1211.     lodsb                             ; Get next source bitmap byte
  1212.     or    al,al                       ; If not zero then write to dest.
  1213.     jz    @@NoPixel                   ; otherwise skip to next byte
  1214.     mov   es:[di],al
  1215. @@NoPixel:
  1216.     inc   di
  1217.     loop  @@ColLoop                   ; loop if more columns left
  1218.     add   di,[LineInc]                ; Move to next row
  1219.     dec   bl                          ; decrement row counter
  1220.     jnz   @@RowLoop                   ; Jump if more rows left
  1221.     pop   si                          ; Restore SI and set to offset of
  1222.     add   si,[PlaneInc]               ; first vis pixel in next plane data
  1223.     pop   di                          ; Restore bitmaps start dest byte
  1224.     rol   ah,1                        ; Shift mask for next plane
  1225.     adc   di,0                        ; if carry increment screen offset
  1226.     dec   bh                          ; Decrement plane counter
  1227.     jnz   @@PlaneLoop                 ; Jump if more planes left
  1228.  
  1229.     xor   ax,ax
  1230.     pop   ds                          ; restore data segment
  1231.     pop   di                          ; restore registers
  1232.     pop   si
  1233.     ret
  1234. xputmaskedpbmclipy   endp
  1235.  
  1236. xputmaskedpbmclipxy  proc far X:word,Y:word,ScrnOffs:word,Bitmap:dword
  1237. LOCAL   Plane:byte,CType,LeftSkip,DataInc,AWidth,Height,TopRow,LineInc,PlaneInc:word
  1238.     push  si
  1239.     push  di
  1240.     push  ds
  1241.     cld
  1242.  
  1243.     les   si,[Bitmap]
  1244.  
  1245.     xor   ax,ax
  1246.     mov   [CType],ax
  1247.     mov   al,byte ptr es:[si]         ; AX = width
  1248.     xor   bh,bh
  1249.     mov   bl,byte ptr es:[si+1]       ; BX = height
  1250.  
  1251.     mov   cx,ax                       ; Save AX
  1252.     mul   bx                          ; AX = AX*BX = bytes/plane
  1253.     mov   [PlaneInc],ax               ;  save as PlaneInc
  1254.     mov   ax,cx                       ; Restore AX
  1255.  
  1256.  
  1257.     mov   di,[X]                      ; DI = X coordinate of dest.
  1258.     mov   cx,di                       ; save in CX
  1259.     sar   di,2                        ; convert to address byte
  1260.  
  1261.  
  1262.         ;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;;
  1263.  
  1264.     mov   dx,[TopClip]           ; Compare u.l. Y coord with Top
  1265.     sub   dx,[Y]                  ; clipping border
  1266.     jle   @@NotTopClip            ; jump if VBM not clipped from above
  1267.     cmp   dx,bx
  1268.     jnl   @@NotVisible            ; jump if VBM is completely obscured
  1269.     mov   [TopRow],dx
  1270.     sub   bx,dx
  1271.     add   [Y],dx
  1272.     jmp   short @@VertClipDone
  1273.  
  1274.     ;;;; EXIT FOR COMPLETELY OBSCURED P.B.M's ;;;;;;;;;;;;;;;;;;;;;;
  1275.  
  1276. @@NotVisible:
  1277.     mov   ax,1
  1278.     pop   ds                          ; restore data segment
  1279.     pop   di                          ; restore registers
  1280.     pop   si
  1281.     ret
  1282.  
  1283.     ;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;;
  1284.  
  1285. @@NotTopClip:
  1286.     mov   dx,[BottomClip]
  1287.     sub   dx,[Y]
  1288.     js    @@NotVisible
  1289.     mov   [TopRow],0
  1290.     cmp   dx,bx
  1291.     jg    @@VertClipDone
  1292.     inc   dx
  1293.     mov   bx,dx
  1294.  
  1295. @@VertClipDone:
  1296.  
  1297.     ;;;;; CLIP PROCESSING FOR LEFT CLIP BORDER ;;;;;;;;;;;;;;;;;;;
  1298.  
  1299.     mov   dx,[LeftClip]
  1300.     sub   dx,di
  1301.     jle   @@NotLeftClip
  1302.     cmp   dx,ax
  1303.     jnl   @@NotVisible
  1304.  
  1305.     add   di,dx
  1306.     mov   [LeftSkip],dx
  1307.     mov   [DataInc],dx
  1308.     sub   ax,dx
  1309.     mov   [CType],1
  1310.     jmp   short @@HorizClipDone
  1311.  
  1312.     ;;;;; CLIP PROCESSING FOR RIGHT CLIP BORDER ;;;;;;;;;;;;;;;;;;;
  1313.  
  1314. @@NotLeftClip:
  1315.     mov   dx,[RightClip]
  1316.     sub   dx,di
  1317.     js    @@NotVisible
  1318.     mov   [LeftSkip],0
  1319.     mov   [DataInc],0
  1320.     cmp   dx,ax
  1321.                 jge   @@HorizClipDone       ; was jg
  1322.     inc   dx
  1323.     sub   ax,dx
  1324.     mov   [DataInc],ax
  1325.     mov   ax,dx
  1326.  
  1327.  
  1328.     mov   [CType],-1
  1329.  
  1330. @@HorizClipDone:
  1331.  
  1332.  
  1333.  
  1334.     mov   [AWidth],ax                  ; Save width and height of clipped
  1335.     mov   [Height],bx                 ;  image
  1336.  
  1337.     add   ax,[DataInc]                ; AX = original width of image
  1338.     mul   [TopRow]                    ; Calculate bytes in clipped top
  1339.     add   si,ax             ;  rows
  1340.     add   si,2                        ; Skip dimension bytes in source
  1341.     add   si,[LeftSkip]               ; Skip pixels in front of row that
  1342.                         ;  are clipped
  1343.  
  1344.     mov   bx,[ScrnLogicalByteWidth]  ; Set BX to Logical Screen Width
  1345.     mov   dx,bx                       ; BX - Width of image = No. bytes
  1346.     sub   dx,[AWidth]                  ;  to first byte of next screen
  1347.     mov   [LineInc],dx                ;  row.
  1348.  
  1349.     mov   ax,[Y]                      ; Calculate screen start row
  1350.     mul   bx                          ;  then adding screen offset
  1351.     add   di,ax
  1352.     add   di,[ScrnOffs]
  1353.     mov   ax,es                       ; copy ES to DS
  1354.     mov   ds,ax
  1355.     mov   ax,SCREENSEG               ; Point ES to VGA segment
  1356.     mov   es,ax
  1357.  
  1358.  
  1359.  
  1360.     and   cx,3
  1361.     mov   ah,11h                      ; Set up initial plane mask
  1362.     shl   ah,cl
  1363.  
  1364.     mov   dx,SCINDEX                 ; Prepare VGA for cpu to video writes
  1365.     mov   al,MAPMASK
  1366.     out   dx,al
  1367.     inc   dx
  1368.     mov   [Plane],4                   ; Set plane counter to 4
  1369.     mov   bh,byte ptr [AWidth]         ; set bh to width for fast looping
  1370. @@PlaneLoop:
  1371.     push  di        ; Save bitmap's start dest. offset
  1372.     push  si
  1373.     mov   bl,byte ptr [Height]        ; Reset row counter (BL)
  1374.     mov   al,ah
  1375.     out   dx,al                       ; set vga write plane
  1376. @@RowLoop:
  1377.     mov   cl,bh                       ; Reset Column counter cl
  1378.     jcxz   @@NoWidth
  1379. @@ColLoop:
  1380.     lodsb                     ; Get next source bitmap byte
  1381.     or    al,al                       ; If not zero then write to dest.
  1382.     jz    @@NoPixel                   ; otherwise skip to next byte
  1383.     mov   es:[di],al
  1384. @@NoPixel:
  1385.     inc   di
  1386.     loop @@ColLoop
  1387. @@NoWidth:
  1388.     add   si,[DataInc]                ; Move to next source row
  1389.     add   di,[LineInc]                ; Move to next screen row
  1390.     dec   bl                          ; decrement row counter
  1391.     jnz   @@RowLoop                   ; Jump if more rows left
  1392.     pop   si                          ; Restore SI and set to offset of
  1393.     add   si,[PlaneInc]               ; first vis pixel in next plane data
  1394.     pop   di                          ; Restore bitmaps start dest byte
  1395.     rol   ah,1              ; Shift mask for next plane
  1396.  
  1397.     ; Plane Transition (A HACK but it works!)
  1398.  
  1399.     jnb   @@Nocarry                   ; Jump if not plane transition
  1400.     mov   bl,ah                       ; Save Plane Mask
  1401.     mov   ax,[CType]                  ; set AX to clip type inc variable
  1402.     add   bh,al                       ; Update advancing variables
  1403.     sub   [DataInc],ax                ;
  1404.     sub   [LineInc],ax                ;
  1405.     cmp   al,0                        ; What type of clip do we have
  1406.     mov   ah,bl                       ;   restore Plane mask
  1407.     jg    @@RightAdvance              ; jump on a right clip!
  1408.     inc   di                          ; otherwise increment DI
  1409.     jmp   @@Nocarry
  1410. @@RightAdvance:
  1411.     dec   si
  1412. @@Nocarry:
  1413.     dec   [Plane]                     ; Decrement plane counter
  1414.     jnz   @@PlaneLoop                 ; Jump if more planes left
  1415.  
  1416.     xor   ax,ax
  1417.     pop   ds                          ; restore data segment
  1418.     pop   di                          ; restore registers
  1419.     pop   si
  1420.     ret
  1421. xputmaskedpbmclipxy  endp
  1422.  
  1423. xputpbmclipx  proc far X:word,Y:word,ScrnOffs:word,Bitmap:dword
  1424. LOCAL   Plane:byte,CType,LeftSkip,DataInc,AWidth,Height,TopRow,LineInc:word
  1425.     push  si
  1426.     push  di
  1427.     push  ds
  1428.     cld
  1429.  
  1430.     les   si,[Bitmap]
  1431.  
  1432.     xor   ax,ax
  1433.     mov   [CType],ax
  1434.     mov   al,byte ptr es:[si]         ; AX = width
  1435.  
  1436.  
  1437.     mov   di,[X]                      ; DI = X coordinate of dest.
  1438.     mov   cx,di                       ; save in CX
  1439.     sar   di,2                        ; convert to address byte
  1440.  
  1441.  
  1442.  
  1443.     ;;;;; CLIP PROCESSING FOR LEFT CLIP BORDER ;;;;;;;;;;;;;;;;;;;
  1444.  
  1445.     mov   dx,[LeftClip]
  1446.     sub   dx,di
  1447.     jle   @@NotLeftClip
  1448.     cmp   dx,ax
  1449.     jnl   @@NotVisible
  1450.  
  1451.     add   di,dx
  1452.     mov   [LeftSkip],dx
  1453.     mov   [DataInc],dx
  1454.     sub   ax,dx
  1455.     mov   [CType],1
  1456.     jmp   short @@HorizClipDone
  1457.  
  1458.     ;;;; EXIT FOR COMPLETELY OBSCURED P.B.M's ;;;;;;;;;;;;;;;;;;;;;;
  1459.  
  1460. @@NotVisible:
  1461.     mov   ax,1
  1462.     pop   ds                          ; restore data segment
  1463.     pop   di                          ; restore registers
  1464.     pop   si
  1465.     ret
  1466.  
  1467.     ;;;;; CLIP PROCESSING FOR RIGHT CLIP BORDER ;;;;;;;;;;;;;;;;;;;
  1468.  
  1469. @@NotLeftClip:
  1470.     mov   dx,[RightClip]
  1471.     sub   dx,di
  1472.     js    @@NotVisible
  1473.     mov   [LeftSkip],0
  1474.     mov   [DataInc],0
  1475.     cmp   dx,ax
  1476.                 jge   @@HorizClipDone       ; was jg
  1477.     inc   dx
  1478.     sub   ax,dx
  1479.     mov   [DataInc],ax
  1480.     mov   ax,dx
  1481.     mov   [CType],-1
  1482.  
  1483. @@HorizClipDone:
  1484.  
  1485.     xor   bh,bh
  1486.     mov   bl,byte ptr es:[si+1]       ; BX = height
  1487.  
  1488.     mov   [AWidth],ax                  ; Save width and height of clipped
  1489.     mov   [Height],bx                 ;  image
  1490.  
  1491.  
  1492.     add   si,2                        ; Skip dimension bytes in source
  1493.     add   si,[LeftSkip]               ; Skip pixels in front of row that
  1494.                         ;  are clipped
  1495.  
  1496.  
  1497.     mov   bx,[ScrnLogicalByteWidth]  ; Set BX to Logical Screen Width
  1498.     mov   dx,bx                       ; BX - Width of image = No. bytes
  1499.     sub   dx,ax                       ;  to first byte of next screen
  1500.     mov   [LineInc],dx                ;  row.
  1501.  
  1502.     mov   ax,[Y]                      ; Calculate screen start row
  1503.     mul   bx                          ;  then adding screen offset
  1504.     add   di,ax
  1505.     add   di,[ScrnOffs]
  1506.     mov   ax,es                       ; copy ES to DS
  1507.     mov   ds,ax
  1508.     mov   ax,SCREENSEG               ; Point ES to VGA segment
  1509.     mov   es,ax
  1510.  
  1511.     and   cx,3
  1512.     mov   ah,11h                      ; Set up initial plane mask
  1513.     shl   ah,cl
  1514.  
  1515.     mov   dx,SCINDEX                 ; Prepare VGA for cpu to video writes
  1516.     mov   al,MAPMASK
  1517.     out   dx,al
  1518.     inc   dx
  1519.     mov   [Plane],4                   ; Set plane counter to 4
  1520.     mov   bh,byte ptr [AWidth]         ; set bh to width for fast looping
  1521. @@PlaneLoop:
  1522.     push  di        ; Save bitmap's start dest. offset
  1523.     mov   bl,byte ptr [Height]        ; Reset row counter (BL)
  1524.     mov   al,ah
  1525.     out   dx,al                       ; set vga write plane
  1526. @@RowLoop:
  1527.     mov   cl,bh                       ; Reset Column counter cl
  1528.     shr   cl,1
  1529.     rep   movsw                       ; Copy a complete row
  1530.     adc   cl,0
  1531.     rep   movsb
  1532.     add   si,[DataInc]                ; Move to next source row
  1533.     add   di,[LineInc]                ; Move to next screen row
  1534.     dec   bl                          ; decrement row counter
  1535.     jnz   @@RowLoop                   ; Jump if more rows left
  1536.     pop   di                          ; Restore bitmaps start dest byte
  1537.     rol   ah,1              ; Shift mask for next plane
  1538.  
  1539.     ; Plane Transition (A HACK but it works!)
  1540.  
  1541.     jnb   @@Nocarry                   ; Jump if not plane transition
  1542.     mov   bl,ah                       ; Save Plane Mask
  1543.     mov   ax,[CType]                  ; set AX to clip type inc variable
  1544.     add   bh,al                       ; Update advancing variables
  1545.     sub   [DataInc],ax                ;
  1546.     sub   [LineInc],ax                ;
  1547.     cmp   al,0                        ; What type of clip do we have
  1548.     mov   ah,bl                       ;   restore Plane mask
  1549.     jg    @@RightAdvance              ; jump on a right clip!
  1550.     inc   di                          ; otherwise increment DI
  1551.     jmp   @@Nocarry
  1552. @@RightAdvance:
  1553.     dec si
  1554. @@Nocarry:
  1555.     dec   [Plane]                     ; Decrement plane counter
  1556.     jnz   @@PlaneLoop                 ; Jump if more planes left
  1557.  
  1558.     xor   ax,ax
  1559.     pop   ds                          ; restore data segment
  1560.     pop   di                          ; restore registers
  1561.     pop   si
  1562.     ret
  1563. xputpbmclipx  endp
  1564.  
  1565. xputpbmclipy  proc far X:word,Y:word,ScrnOffs:word,Bitmap:dword
  1566. LOCAL   AWidth,Height,TopRow,LineInc,PlaneInc:word
  1567.     push  si
  1568.     push  di
  1569.     push  ds
  1570.     cld
  1571.  
  1572.     les   si,[Bitmap]
  1573.  
  1574.     xor   bh,bh
  1575.     mov   bl,byte ptr es:[si+1]   ; BX = height
  1576.     ;mov   [Height],bx
  1577.  
  1578.     xor   ah,ah
  1579.     mov   al,byte ptr es:[si]     ; AX = width
  1580.     mov   [AWidth],ax
  1581.  
  1582.     mov   cx,ax                       ; Save AX
  1583.     mul   bx                          ; AX = AX*BX = bytes/plane
  1584.     mov   [PlaneInc],ax               ;  save as PlaneInc
  1585.     mov   ax,cx                       ; Restore AX
  1586.  
  1587.     mov   di,[X]
  1588.     mov   cx,di
  1589.     and   cx,3
  1590.     shr   di,2
  1591.  
  1592.     ;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;;
  1593.  
  1594.     mov   dx,[TopClip]           ; Compare u.l. Y coord with Top
  1595.     sub   dx,[Y]                  ; clipping border
  1596.     jle   @@NotTopClip            ; jump if VBM not clipped from above
  1597.     cmp   dx,bx
  1598.     jnl   @@NotVisible            ; jump if VBM is completely obscured
  1599.     mov   [TopRow],dx
  1600.     sub   bx,dx
  1601.     add   [Y],dx
  1602.     jmp   short @@VertClipDone
  1603.  
  1604.     ;;;; EXIT FOR COMPLETELY OBSCURED P.B.M's ;;;;;;;;;;;;;;;;;;;;;;
  1605.  
  1606. @@NotVisible:
  1607.     mov   ax,1
  1608.     pop   ds                          ; restore data segment
  1609.     pop   di                          ; restore registers
  1610.     pop   si
  1611.     ret
  1612.  
  1613.     ;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;;
  1614.  
  1615. @@NotTopClip:
  1616.     mov   dx,[BottomClip]
  1617.     sub   dx,[Y]
  1618.     js    @@NotVisible
  1619.     mov   [TopRow],0
  1620.     cmp   dx,bx
  1621.     jg    @@VertClipDone
  1622.     inc   dx
  1623.     mov   bx,dx
  1624.  
  1625. @@VertClipDone:
  1626.  
  1627.     mov   [Height],bx                 ; Calculate relative offset in data
  1628.     mul   [TopRow]                    ;  of first visible scanline
  1629.     add   ax,2                        ; Skip dimension bytes in source
  1630.     add   si,ax                       ; Skip top rows that arent visible
  1631.  
  1632.  
  1633.     mov   ax,[Y]                      ; Calculate screen row
  1634.     mov   bx,[ScrnLogicalByteWidth]  ;  by mult. Y coord by Screen
  1635.     mul   bx                          ;  width then adding screen offset
  1636.     add   di,ax
  1637.     add   di,[ScrnOffs]
  1638.     sub   bx,[AWidth]                  ; calculate difference from end of
  1639.     mov   [LineInc],bx                ; b.m. in curr line to beginning of
  1640.                         ; b.m. on next scan line
  1641.     mov   ax,es                       ; copy ES to DS
  1642.     mov   ds,ax
  1643.     mov   ax,SCREENSEG               ; Point ES to VGA segment
  1644.     mov   es,ax
  1645.  
  1646.     mov   ah,11h                      ; Set up initial plane mask
  1647.     shl   ah,cl
  1648.  
  1649.     mov   dx,SCINDEX                 ; Prepare VGA for cpu to video writes
  1650.     mov   al,MAPMASK
  1651.     out   dx,al
  1652.     inc   dx
  1653.     mov   bh,4                        ; Set plane counter to 4
  1654. @@PlaneLoop:
  1655.     push  di        ; Save bitmap's start dest. offset
  1656.     push  si                          ; Save Bitmaps data offset
  1657.     mov   bl,byte ptr [Height]        ; Reset row counter (BL)
  1658.     mov   al,ah
  1659.     out   dx,al                       ; set vga write plane
  1660. @@RowLoop:
  1661.     mov   cl,byte ptr [AWidth]         ; Reset Column counter cl
  1662.     shr   cl,1
  1663.     rep   movsw                       ; Copy a complete row
  1664.     adc   cl,0
  1665.     rep   movsb
  1666.  
  1667.     add   di,[LineInc]                ; Move to next row
  1668.     dec   bl                          ; decrement row counter
  1669.     jnz   @@RowLoop                   ; Jump if more rows left
  1670.     pop   si                          ; Restore SI and set to offset of
  1671.     add   si,[PlaneInc]               ; first vis pixel in next plane data
  1672.     pop   di                          ; Restore bitmaps start dest byte
  1673.     rol   ah,1                        ; Shift mask for next plane
  1674.     adc   di,0                        ; if carry increment screen offset
  1675.     dec   bh                          ; Decrement plane counter
  1676.     jnz   @@PlaneLoop                 ; Jump if more planes left
  1677.  
  1678.     xor   ax,ax
  1679.     pop   ds                          ; restore data segment
  1680.     pop   di                          ; restore registers
  1681.     pop   si
  1682.     ret
  1683. xputpbmclipy   endp
  1684.  
  1685.  
  1686. xputpbmclipxy  proc far X:word,Y:word,ScrnOffs:word,Bitmap:dword
  1687. LOCAL   Plane:byte,CType,LeftSkip,DataInc,AWidth,Height,TopRow,LineInc,PlaneInc:word
  1688.     push  si
  1689.     push  di
  1690.     push  ds
  1691.     cld
  1692.  
  1693.     les   si,[Bitmap]
  1694.  
  1695.     xor   ax,ax
  1696.     mov   [CType],ax
  1697.     mov   al,byte ptr es:[si]         ; AX = width
  1698.     xor   bh,bh
  1699.     mov   bl,byte ptr es:[si+1]       ; BX = height
  1700.  
  1701.     mov   cx,ax                       ; Save AX
  1702.     mul   bx                          ; AX = AX*BX = bytes/plane
  1703.     mov   [PlaneInc],ax               ;  save as PlaneInc
  1704.     mov   ax,cx                       ; Restore AX
  1705.  
  1706.  
  1707.     mov   di,[X]                      ; DI = X coordinate of dest.
  1708.     mov   cx,di                       ; save in CX
  1709.     sar   di,2                        ; convert to address byte
  1710.  
  1711.  
  1712.         ;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;;
  1713.  
  1714.     mov   dx,[TopClip]           ; Compare u.l. Y coord with Top
  1715.     sub   dx,[Y]                  ; clipping border
  1716.     jle   @@NotTopClip            ; jump if VBM not clipped from above
  1717.     cmp   dx,bx
  1718.     jnl   @@NotVisible            ; jump if VBM is completely obscured
  1719.     mov   [TopRow],dx
  1720.     sub   bx,dx
  1721.     add   [Y],dx
  1722.     jmp   short @@VertClipDone
  1723.  
  1724.     ;;;; EXIT FOR COMPLETELY OBSCURED P.B.M's ;;;;;;;;;;;;;;;;;;;;;;
  1725.  
  1726. @@NotVisible:
  1727.     mov   ax,1
  1728.     pop   ds                          ; restore data segment
  1729.     pop   di                          ; restore registers
  1730.     pop   si
  1731.     ret
  1732.  
  1733.     ;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;;
  1734.  
  1735. @@NotTopClip:
  1736.     mov   dx,[BottomClip]
  1737.     sub   dx,[Y]
  1738.     js    @@NotVisible
  1739.     mov   [TopRow],0
  1740.     cmp   dx,bx
  1741.     jg    @@VertClipDone
  1742.     inc   dx
  1743.     mov   bx,dx
  1744.  
  1745. @@VertClipDone:
  1746.  
  1747.     ;;;;; CLIP PROCESSING FOR LEFT CLIP BORDER ;;;;;;;;;;;;;;;;;;;
  1748.  
  1749.     mov   dx,[LeftClip]
  1750.     sub   dx,di
  1751.     jle   @@NotLeftClip
  1752.     cmp   dx,ax
  1753.     jnl   @@NotVisible
  1754.  
  1755.     add   di,dx
  1756.     mov   [LeftSkip],dx
  1757.     mov   [DataInc],dx
  1758.     sub   ax,dx
  1759.     mov   [CType],1
  1760.     jmp   short @@HorizClipDone
  1761.  
  1762.     ;;;;; CLIP PROCESSING FOR RIGHT CLIP BORDER ;;;;;;;;;;;;;;;;;;;
  1763.  
  1764. @@NotLeftClip:
  1765.     mov   dx,[RightClip]
  1766.     sub   dx,di
  1767.     js    @@NotVisible
  1768.     mov   [LeftSkip],0
  1769.     mov   [DataInc],0
  1770.     cmp   dx,ax
  1771.                 jge   @@HorizClipDone       ; was jg
  1772.     inc   dx
  1773.     sub   ax,dx
  1774.     mov   [DataInc],ax
  1775.     mov   ax,dx
  1776.     mov   [CType],-1
  1777.  
  1778. @@HorizClipDone:
  1779.  
  1780.  
  1781.  
  1782.     mov   [AWidth],ax                  ; Save width and height of clipped
  1783.     mov   [Height],bx                 ;  image
  1784.  
  1785.     add   ax,[DataInc]                ; AX = original width of image
  1786.     mul   [TopRow]                    ; Calculate bytes in clipped top
  1787.     add   si,ax             ;  rows
  1788.     add   si,2                        ; Skip dimension bytes in source
  1789.     add   si,[LeftSkip]               ; Skip pixels in front of row that
  1790.                         ;  are clipped
  1791.  
  1792.     mov   bx,[ScrnLogicalByteWidth]  ; Set BX to Logical Screen Width
  1793.     mov   dx,bx                       ; BX - Width of image = No. bytes
  1794.     sub   dx,[AWidth]                  ;  to first byte of next screen
  1795.     mov   [LineInc],dx                ;  row.
  1796.  
  1797.     mov   ax,[Y]                      ; Calculate screen start row
  1798.     mul   bx                          ;  then adding screen offset
  1799.     add   di,ax
  1800.     add   di,[ScrnOffs]
  1801.     mov   ax,es                       ; copy ES to DS
  1802.     mov   ds,ax
  1803.     mov   ax,SCREENSEG               ; Point ES to VGA segment
  1804.     mov   es,ax
  1805.  
  1806.  
  1807.  
  1808.     and   cx,3
  1809.     mov   ah,11h                      ; Set up initial plane mask
  1810.     shl   ah,cl
  1811.  
  1812.     mov   dx,SCINDEX                 ; Prepare VGA for cpu to video writes
  1813.     mov   al,MAPMASK
  1814.     out   dx,al
  1815.     inc   dx
  1816.     mov   [Plane],4                   ; Set plane counter to 4
  1817.     mov   bh,byte ptr [AWidth]         ; set bh to width for fast looping
  1818. @@PlaneLoop:
  1819.     push  di        ; Save bitmap's start dest. offset
  1820.     push  si
  1821.     mov   bl,byte ptr [Height]        ; Reset row counter (BL)
  1822.     mov   al,ah
  1823.     out   dx,al                       ; set vga write plane
  1824. @@RowLoop:
  1825.     mov   cl,bh                       ; Reset Column counter cl
  1826.     shr   cl,1
  1827.     rep   movsw                       ; Copy a complete row
  1828.     adc   cl,0
  1829.     rep   movsb
  1830.     add   si,[DataInc]                ; Move to next source row
  1831.     add   di,[LineInc]                ; Move to next screen row
  1832.     dec   bl                          ; decrement row counter
  1833.     jnz   @@RowLoop                   ; Jump if more rows left
  1834.     pop   si                          ; Restore SI and set to offset of
  1835.     add   si,[PlaneInc]               ; first vis pixel in next plane data
  1836.     pop   di                          ; Restore bitmaps start dest byte
  1837.     rol   ah,1              ; Shift mask for next plane
  1838.  
  1839.     ; Plane Transition (A HACK but it works!)
  1840.  
  1841.     jnb   @@Nocarry                   ; Jump if not plane transition
  1842.     mov   bl,ah                       ; Save Plane Mask
  1843.     mov   ax,[CType]                  ; set AX to clip type inc variable
  1844.     add   bh,al                       ; Update advancing variables
  1845.     sub   [DataInc],ax                ;
  1846.     sub   [LineInc],ax                ;
  1847.     cmp   al,0                        ; What type of clip do we have
  1848.     mov   ah,bl                       ;   restore Plane mask
  1849.     jg    @@RightAdvance              ; jump on a right clip!
  1850.     inc   di                          ; otherwise increment DI
  1851.     jmp   @@Nocarry
  1852. @@RightAdvance:
  1853.     dec si
  1854. @@Nocarry:
  1855.     dec   [Plane]                     ; Decrement plane counter
  1856.     jnz   @@PlaneLoop                 ; Jump if more planes left
  1857.  
  1858.     xor   ax,ax
  1859.     pop   ds                          ; restore data segment
  1860.     pop   di                          ; restore registers
  1861.     pop   si
  1862.     ret
  1863. xputpbmclipxy  endp
  1864.  
  1865. xstorevbmimage  proc far VramOffs:word,AAlign:word,LBitmap:dword
  1866. LOCAL BMWidth:byte
  1867.  
  1868.     push  si
  1869.     push  di
  1870.     push  ds
  1871.     cld
  1872.  
  1873.     mov   ax,SCREENSEG               ; Point ES to screen segment
  1874.     mov   es,ax
  1875.     mov   di,[VramOffs]               ; Point ES:DI to VRAM dest start
  1876.     mov   bx,[AAlign]                  ; Set BL to first pixel plane align
  1877.                 and   bl,03h
  1878.  
  1879.     lds   si,[LBitmap]                ; DS:SI -> source linear Bitmap
  1880.                 lodsw                             ; Al = B.M. width (bytes) AH = B.M.
  1881.     mov   bh,ah                       ; Save source bitmap dimensions
  1882.     mov   [BMWidth],al                ;
  1883.  
  1884.     mov   dx,SCINDEX                 ; Initialize Map Mask for plane
  1885.     mov   al,MAPMASK                 ; selection
  1886.                 out   dx,al
  1887.     inc   dx
  1888.     xor   ch,ch                       ; clear CH
  1889. @@RowLoop:
  1890.     mov   cl,bl                       ; Set initial plane for current
  1891.     mov   ah,11h                      ; allignment
  1892.     shl   ah,cl
  1893.  
  1894.     mov   cl,[BMWidth]                ; Initialize column counter
  1895. @@ColLoop:
  1896.     mov   al,ah
  1897.     out   dx,al                       ; set vga write plane
  1898.     lodsb                             ; load next LBM pixel
  1899.     mov   es:[di],al                  ; store it in Video Ram
  1900.     shl   ah,1                        ; rotate plane mask
  1901.     jnb   @@NoAddrIncr                ; Time to increment dest address ?
  1902.     inc   di                          ; Yes: increment addr and reset
  1903.     mov   ah,11h                      ;  plane mask to plane 0
  1904. @@NoAddrIncr:
  1905.     loop  @@ColLoop                   ; Loop to next pixel column
  1906.     cmp   ah,11h
  1907. ; je    @@skip
  1908.     inc   di          ; Increment dest addr
  1909. ;@@skip:
  1910.     dec   bh                          ; Decrement row counter
  1911.     jnz   @@RowLoop                   ; Jump if more rows to go
  1912.     mov   ax,di                       ; calculate video RAM consumed and
  1913.     sub   ax,[VramOffs]               ;   return value
  1914.  
  1915.     pop   ds                          ; restore data segment
  1916.     pop   di                          ; restore registers
  1917.     pop   si
  1918.     ret
  1919. xstorevbmimage  endp
  1920.  
  1921.  
  1922. xputmaskedvbm  proc far X:word,Y:word,ScrnOffs:word,SrcVBM:dword
  1923. LOCAL VBMWidth:word,VBMHeight:word,NextLineIncr:word
  1924.     push  si
  1925.     push  di
  1926.     push  ds
  1927.     cld
  1928.  
  1929.     mov   ax,SCREENSEG               ; Point es to VGA segment
  1930.     mov   es,ax
  1931.     mov   ax,[Y]                      ; Calculate dest screen row
  1932.     mov   cx,[ScrnLogicalByteWidth]  ;  by mult. dest Y coord by Screen
  1933.     mul   cx                          ;  width then adding screen offset
  1934.  
  1935.     mov   di,[ScrnOffs]               ;  store result in DI
  1936.     add   di,ax
  1937.     mov   si,[X]                      ; Load X coord into CX and make a
  1938.     mov   bx,si                       ;  copy in DX
  1939.     shr   bx,2                        ; Find starting byte in dest row
  1940.     add   di,bx                       ;  add to DI giving screen offset of
  1941.                                                                                     ;  first pixel's byte
  1942.  
  1943.     and   si,3                        ; get pixel alignment in si
  1944.  
  1945.     lds   bx,[SrcVBM]                 ; DS:BX -> VBM data structure
  1946.     shl   si,2                        ; si = offset of data  for curr
  1947.                         ; alignment
  1948.  
  1949.     mov ax,word ptr [bx+ImageHeight]  ; Get image height
  1950.     mov   [VBMHeight],ax
  1951.     mov ax,word ptr [bx+ImageWidth]   ; Get image width
  1952.     mov   [VBMWidth],ax
  1953.  
  1954.     sub   cx,ax                       ; NextLineIncr = bytes to the begin.
  1955.     mov   [NextLineIncr],cx           ;  of bitmaps next row on screen
  1956.     mov   dx,[bx+MaskPtr+AlignData+si]  ; DS:SI -> mask data
  1957.     mov   bx,[bx+ImagePtr+AlignData+si] ; ES:BX -> source video bitmap
  1958.     mov   si,dx
  1959.  
  1960.     mov   dx,GCINDEX                 ; Set bit mask for all bits from
  1961.     mov   ax,BITMASK                 ; VGA latches and none from CPU
  1962.     out   dx,ax
  1963.  
  1964.     mov   dx,SCINDEX                 ; Point SC register to map mask
  1965.     mov   al,MAPMASK                 ; in preperation for masking data
  1966.     out   dx,al
  1967.     inc   dx                          ; Point dx to SC data register
  1968.     mov   ah,byte ptr [VBMHeight]     ; AH = Scanline loop counter
  1969.  
  1970. @@RowLoop:
  1971.     mov   cx,[VBMWidth]               ; Width in bytes across
  1972.  
  1973. @@ColumnLoop:
  1974.     lodsb
  1975.     out   dx,al
  1976.     mov   al,es:[bx]                  ; load latches from source bitmap
  1977.     stosb                             ; store latches to dest. bitmap
  1978.     inc   bx
  1979.     loop  @@ColumnLoop
  1980.  
  1981.     add   di,[NextLineIncr]           ; point to start of next dest row
  1982.     dec   ah                          ; decrement scan line counter
  1983.     jnz   @@RowLoop                   ; jump if more scanlines left
  1984.  
  1985.     mov   dx,GCINDEX+1               ; Restore bitmask to the default -
  1986.     mov   al,0ffh                     ;  all data from cpu
  1987.     out   dx,al
  1988.  
  1989.     pop   ds                          ; restore data segment
  1990.     pop   di                          ; restore registers
  1991.     pop   si
  1992.     ret
  1993. xputmaskedvbm  endp
  1994.  
  1995.  
  1996. xputmaskedvbmclipx  proc far X:word,Y:word,ScrnOffs:word,SrcVBM:dword
  1997. LOCAL DataInc,LeftSkip,VBMWidth,VBMHeight,NextLineIncr:word
  1998.     push  si
  1999.     push  di
  2000.     push  ds
  2001.     cld
  2002.  
  2003.     mov   di,[X]                  ; load X coord int DI and make a
  2004.     mov   si,di                   ;  copy in SI
  2005.     sar   di,2                    ; Find Byte offset of X coord
  2006.  
  2007.     and   si,3                    ; Calculate pixels plane alignment
  2008.     shl   si,2                    ; Prepare to lookup mask & data
  2009.     les   bx,[SrcVBM]             ; ES:BX -> begining of VBM data
  2010.  
  2011.     mov   cx,es:[bx+ImageWidth]   ; Get image width and save in CX
  2012.  
  2013.  
  2014.  
  2015.     ;;;;; CLIP PROCESSING FOR LEFT CLIP BORDER ;;;;;;;;;;;;;;;;;;;
  2016.  
  2017.     mov   dx,[LeftClip]
  2018.     sub   dx,di
  2019.     jle   @@NotLeftClip
  2020.     cmp   dx,cx
  2021.     jnl   @@NotVisible
  2022.     add   di,dx
  2023.     mov   [LeftSkip],dx
  2024.     mov   [DataInc],dx
  2025.     sub   cx,dx
  2026.     jmp   short @@HorizClipDone
  2027.  
  2028.                 ;;;; EXIT FOR COMPLETELY OBSCURED V.B.M's ;;;;;;;;;;;;;;;;;;;;;;
  2029.  
  2030. @@NotVisible:
  2031.     mov   ax,1
  2032.     pop   ds                          ; restore data segment
  2033.     pop   di                          ; restore registers
  2034.     pop   si
  2035.     ret
  2036.  
  2037.     ;;;;; CLIP PROCESSING FOR RIGHT CLIP BORDER ;;;;;;;;;;;;;;;;;;;
  2038.  
  2039. @@NotLeftClip:
  2040.     mov   dx,[RightClip]
  2041.     sub   dx,di
  2042.     js    @@NotVisible
  2043.     mov   [LeftSkip],0
  2044.     mov   [DataInc],0
  2045.     cmp   dx,cx
  2046.     jge   @@HorizClipDone
  2047.     inc   dx
  2048.     sub   cx,dx
  2049.     mov   [DataInc],cx
  2050.     mov   cx,dx
  2051.  
  2052. @@HorizClipDone:
  2053.  
  2054.  
  2055.     add   di,[ScrnOffs]           ; Add the current page offset
  2056.     mov   [VBMWidth],cx
  2057.     mov   ax,es:[bx+ImageHeight]  ; Get image height and save in AX
  2058.     mov   [VBMHeight],ax
  2059.  
  2060.  
  2061.     ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2062.  
  2063.     mov   ax,[Y]                      ; Calculate dest screen row
  2064.     mov   cx,[ScrnLogicalByteWidth]  ;  by mult. dest Y coord by Screen
  2065.     mul   cx                          ;  width then adding screen offset
  2066.     add   di,ax                       ; Add Dest Screen Row to di
  2067.     sub   cx,[VBMWidth]
  2068.     mov   [NextLineIncr],cx
  2069.  
  2070.     mov   ax,es                       ; copy ES to DS
  2071.     mov   ds,ax
  2072.     mov   ax,SCREENSEG               ; Point es to VGA segment
  2073.     mov   es,ax
  2074.  
  2075.     mov   ax,[bx+MaskPtr+AlignData+si]  ; DS:SI -> mask data
  2076.     mov   bx,[bx+ImagePtr+AlignData+si] ; ES:BX -> source video bitmap
  2077.     mov   si,ax
  2078.  
  2079.     mov   ax,[LeftSkip]               ; Skip data/mask bytes in
  2080.     add   bx,ax                       ; each row that have been clipped
  2081.     add   si,ax                       ; by the L.H.S border
  2082.  
  2083.  
  2084.     mov   dx,GCINDEX                 ; Set bit mask for all bits from
  2085.     mov   ax,BITMASK                 ; VGA latches and none from CPU
  2086.     out   dx,ax
  2087.     mov   dx,SCINDEX                 ; Point SC register to map mask
  2088.     mov   al,MAPMASK                 ; in preperation for masking data
  2089.     out   dx,al
  2090.     inc   dx                          ; Point dx to SC data register
  2091.     mov   ah,byte ptr [VBMHeight]     ; AH = Scanline loop counter
  2092.  
  2093. @@RowLoop:
  2094.     mov   cx,[VBMWidth]               ; Width in bytes across
  2095.  
  2096. @@ColumnLoop:
  2097.     lodsb
  2098.     out   dx,al
  2099.     mov   al,es:[bx]                  ; load latches from source bitmap
  2100.     stosb                             ; store latches to dest. bitmap
  2101.     inc   bx
  2102.     loop  @@ColumnLoop
  2103.     add   bx,[DataInc]
  2104.     add   si,[DataInc]
  2105.     add   di,[NextLineIncr]           ; point to start of next dest row
  2106.     dec   byte ptr ah                 ; decrement scan line counter
  2107.     jnz   @@RowLoop                   ; jump if more scanlines left
  2108.  
  2109.     mov   dx,GCINDEX+1               ; Restore bitmask to the default -
  2110.     mov   al,0ffh                     ;  all data from cpu
  2111.     out   dx,al
  2112.     xor   ax,ax
  2113.     pop   ds                          ; restore data segment
  2114.     pop   di                          ; restore registers
  2115.     pop   si
  2116.     ret
  2117. xputmaskedvbmclipx  endp
  2118.  
  2119.  
  2120. xputmaskedvbmclipy  proc far X:word,Y:word,ScrnOffs:word,SrcVBM:dword
  2121. LOCAL VBMWidth,VBMHeight,TopRow,NextLineIncr:word
  2122.     push  si
  2123.     push  di
  2124.     push  ds
  2125.     cld
  2126.  
  2127.     mov   di,[X]                  ; load X coord int DI and make a
  2128.     mov   si,di                   ;  copy in SI
  2129.  
  2130.  
  2131.     and   si,3                    ; Calculate pixels plane alignment
  2132.     shl   si,2                    ; Prepare to lookup mask & data
  2133.     les   bx,[SrcVBM]             ; ES:BX -> begining of VBM data
  2134.  
  2135.  
  2136.     mov   ax,es:[bx+ImageHeight]  ; Get image height and save in AX
  2137.  
  2138.  
  2139.  
  2140.     ;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;;
  2141.  
  2142.     mov   dx,[TopClip]           ; Compare u.l. Y coord with Top
  2143.     sub   dx,[Y]                  ; clipping border
  2144.     jle   @@NotTopClip            ; jump if VBM not clipped from above
  2145.     cmp   dx,ax
  2146.     jnl   @@NotVisible            ; jump if VBM is completely obscured
  2147.     mov   [TopRow],dx
  2148.     sub   ax,dx
  2149.     add   [Y],dx
  2150.     jmp   short @@VertClipDone
  2151.  
  2152.     ;;;; EXIT FOR COMPLETELY OBSCURED V.B.M's ;;;;;;;;;;;;;;;;;;;;;;
  2153.  
  2154. @@NotVisible:
  2155.     mov   ax,1
  2156.     pop   ds                          ; restore data segment
  2157.     pop   di                          ; restore registers
  2158.     pop   si
  2159.     ret
  2160.  
  2161.     ;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;;
  2162.  
  2163. @@NotTopClip:
  2164.     mov   dx,[BottomClip]
  2165.     sub   dx,[Y]
  2166.     js    @@NotVisible
  2167.     mov   [TopRow],0
  2168.     cmp   dx,ax
  2169.     jg    @@VertClipDone
  2170.     inc   dx
  2171.     mov   ax,dx
  2172.  
  2173. @@VertClipDone:
  2174.  
  2175.  
  2176.     shr   di,2                    ; Find Byte offset of X coord
  2177.     add   di,[ScrnOffs]           ; Add the current page offset
  2178.     mov   cx,es:[bx+ImageWidth]   ; Get image width and save in CX
  2179.     mov   [VBMWidth],cx
  2180.     mov   [VBMHeight],ax
  2181.  
  2182.     ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2183.  
  2184.     mov   ax,[Y]                      ; Calculate dest screen row
  2185.     mov   cx,[ScrnLogicalByteWidth]  ;  by mult. dest Y coord by Screen
  2186.     mul   cx                          ;  width then adding screen offset
  2187.     add   di,ax                       ; Add Dest Screen Row to di
  2188.     sub   cx,[VBMWidth]
  2189.     mov   [NextLineIncr],cx
  2190.  
  2191.     mov   ax,es                       ; copy ES to DS
  2192.     mov   ds,ax
  2193.     mov   ax,SCREENSEG               ; Point es to VGA segment
  2194.     mov   es,ax
  2195.  
  2196.     mov   ax,[bx+MaskPtr+AlignData+si]  ; DS:SI -> mask data
  2197.     mov   bx,[bx+ImagePtr+AlignData+si] ; ES:BX -> source video bitmap
  2198.     mov   si,ax
  2199.  
  2200.  
  2201.  
  2202.     mov   ax,[VBMWidth]               ; Increment DS:BX and DS:SI to
  2203.     mul   [TopRow]                    ;  skip image/mask data that has
  2204.     add   bx,ax                       ;  been clipped by the top border
  2205.     add   si,ax
  2206.  
  2207.  
  2208.     mov   dx,GCINDEX                 ; Set bit mask for all bits from
  2209.     mov   ax,BITMASK                 ; VGA latches and none from CPU
  2210.     out   dx,ax
  2211.     mov   dx,SCINDEX                 ; Point SC register to map mask
  2212.     mov   al,MAPMASK                 ; in preperation for masking data
  2213.     out   dx,al
  2214.     inc   dx                          ; Point dx to SC data register
  2215.     mov   ah,byte ptr [VBMHeight]     ; AH = Scanline loop counter
  2216.  
  2217. @@RowLoop:
  2218.     mov   cx,[VBMWidth]               ; Width in bytes across
  2219.  
  2220. @@ColumnLoop:
  2221.     lodsb
  2222.     out   dx,al
  2223.     mov   al,es:[bx]                  ; load latches from source bitmap
  2224.     stosb                             ; store latches to dest. bitmap
  2225.     inc   bx
  2226.     loop  @@ColumnLoop
  2227.     add   di,[NextLineIncr]           ; point to start of next dest row
  2228.     dec   byte ptr ah                 ; decrement scan line counter
  2229.     jnz   @@RowLoop                   ; jump if more scanlines left
  2230.  
  2231.     mov   dx,GCINDEX+1               ; Restore bitmask to the default -
  2232.     mov   al,0ffh                     ;  all data from cpu
  2233.     out   dx,al
  2234.  
  2235.     xor   ax,ax
  2236.     pop   ds                          ; restore data segment
  2237.     pop   di                          ; restore registers
  2238.     pop   si
  2239.     ret
  2240. xputmaskedvbmclipy  endp
  2241.  
  2242. xputmaskedvbmclipxy  proc far X:word,Y:word,ScrnOffs:word,SrcVBM:dword
  2243. LOCAL DataInc,LeftSkip,VBMWidth,VBMHeight,TopRow,NextLineIncr:word
  2244.     push  si
  2245.     push  di
  2246.     push  ds
  2247.     cld
  2248.  
  2249.     mov   di,[X]                  ; load X coord int DI and make a
  2250.     mov   si,di                   ;  copy in SI
  2251.     sar   di,2                    ; Find Byte offset of X coord
  2252.     and   si,3                    ; Calculate pixels plane alignment
  2253.     shl   si,2                    ; Prepare to lookup mask & data
  2254.     les   bx,[SrcVBM]             ; ES:BX -> begining of VBM data
  2255.  
  2256.     mov   cx,es:[bx+ImageWidth]   ; Get image width and save in CX
  2257.     mov   ax,es:[bx+ImageHeight]  ; Get image height and save in AX
  2258.  
  2259.  
  2260.  
  2261.     ;;;;; CLIP PROCESSING FOR TOP CLIP BORDER ;;;;;;;;;;;;;;;;;;;;;
  2262.  
  2263.     mov   dx,[TopClip]           ; Compare u.l. Y coord with Top
  2264.     sub   dx,[Y]                  ; clipping border
  2265.     jle   @@NotTopClip            ; jump if VBM not clipped from above
  2266.     cmp   dx,ax
  2267.     jnl   @@NotVisible            ; jump if VBM is completely obscured
  2268.     mov   [TopRow],dx
  2269.     sub   ax,dx
  2270.     add   [Y],dx
  2271.     jmp   short @@VertClipDone
  2272.  
  2273.     ;;;; EXIT FOR COMPLETELY OBSCURED V.B.M's ;;;;;;;;;;;;;;;;;;;;;;
  2274.  
  2275. @@NotVisible:
  2276.     mov   ax,1
  2277.     pop   ds                          ; restore data segment
  2278.     pop   di                          ; restore registers
  2279.     pop   si
  2280.     ret
  2281.  
  2282.     ;;;;; CLIP PROCESSING FOR BOTTOM CLIP BORDER ;;;;;;;;;;;;;;;;;;;
  2283.  
  2284. @@NotTopClip:
  2285.     mov   dx,[BottomClip]
  2286.     sub   dx,[Y]
  2287.     js    @@NotVisible
  2288.     mov   [TopRow],0
  2289.     cmp   dx,ax
  2290.     jg    @@VertClipDone
  2291.     inc   dx
  2292.     mov   ax,dx
  2293.  
  2294. @@VertClipDone:
  2295.  
  2296.     ;;;;; CLIP PROCESSING FOR LEFT CLIP BORDER ;;;;;;;;;;;;;;;;;;;
  2297.  
  2298.  
  2299.     mov   dx,[LeftClip]
  2300.     sub   dx,di
  2301.     jle   @@NotLeftClip
  2302.     cmp   dx,cx
  2303.     jnl   @@NotVisible
  2304.     add   di,dx
  2305.     mov   [LeftSkip],dx
  2306.     mov   [DataInc],dx
  2307.     sub   cx,dx
  2308.     jmp   short @@HorizClipDone
  2309.  
  2310.     ;;;;; CLIP PROCESSING FOR RIGHT CLIP BORDER ;;;;;;;;;;;;;;;;;;;
  2311.  
  2312. @@NotLeftClip:
  2313.     mov   dx,[RightClip]
  2314.     sub   dx,di
  2315.     js    @@NotVisible
  2316.     mov   [LeftSkip],0
  2317.     mov   [DataInc],0
  2318.     cmp   dx,cx
  2319.     jge    @@HorizClipDone
  2320.     inc   dx
  2321.     sub   cx,dx
  2322.     mov   [DataInc],cx
  2323.     mov   cx,dx
  2324.  
  2325. @@HorizClipDone:
  2326.  
  2327.     add   di,[ScrnOffs]           ; Add the current page offset
  2328.     mov   [VBMWidth],cx
  2329.     mov   [VBMHeight],ax
  2330.     ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2331.  
  2332.     mov   ax,[Y]                      ; Calculate dest screen row
  2333.     mov   cx,[ScrnLogicalByteWidth]   ;  by mult. dest Y coord by Screen
  2334.     mul   cx                          ;  width then adding screen offset
  2335.     add   di,ax                       ; Add Dest Screen Row to di
  2336.     sub   cx,[VBMWidth]
  2337.     mov   [NextLineIncr],cx
  2338.  
  2339.     mov   ax,es                       ; copy ES to DS
  2340.     mov   ds,ax
  2341.     mov   ax,SCREENSEG               ; Point es to VGA segment
  2342.     mov   es,ax
  2343.  
  2344.     mov   ax,[bx+MaskPtr+AlignData+si]  ; DS:SI -> mask data
  2345.     mov   bx,[bx+ImagePtr+AlignData+si] ; ES:BX -> source video bitmap
  2346.     mov   si,ax
  2347.  
  2348.  
  2349.  
  2350.     mov   ax,[VBMWidth]               ; Increment DS:BX and DS:SI to
  2351.     add   ax,[DataInc]                ;  skip image/mask data that has
  2352.     mul   [TopRow]                    ;  been clipped by the top border
  2353.     add   ax,[LeftSkip]               ; Skip also data/mask bytes in
  2354.     add   bx,ax                       ; each row that have been clipped
  2355.     add   si,ax                       ; by the L.H.S border
  2356.  
  2357.  
  2358.     mov   dx,GCINDEX                  ; Set bit mask for all bits from
  2359.     mov   ax,BITMASK                  ; VGA latches and none from CPU
  2360.     out   dx,ax
  2361.     mov   dx,SCINDEX                  ; Point SC register to map mask
  2362.     mov   al,MAPMASK                  ; in preperation for masking data
  2363.     out   dx,al
  2364.     inc   dx                          ; Point dx to SC data register
  2365.     mov   ah,byte ptr [VBMHeight]     ; AH = Scanline loop counter
  2366.  
  2367. @@RowLoop:
  2368.     mov   cx,[VBMWidth]               ; Width in bytes across
  2369.  
  2370. @@ColumnLoop:
  2371.     lodsb
  2372.     out   dx,al
  2373.     mov   al,es:[bx]                  ; load latches from source bitmap
  2374.     stosb                             ; store latches to dest. bitmap
  2375.     inc   bx
  2376.     loop  @@ColumnLoop
  2377.     add   bx,[DataInc]
  2378.     add   si,[DataInc]
  2379.     add   di,[NextLineIncr]           ; point to start of next dest row
  2380.     dec   byte ptr ah                 ; decrement scan line counter
  2381.     jnz   @@RowLoop                   ; jump if more scanlines left
  2382.  
  2383.     mov   dx,GCINDEX+1                ; Restore bitmask to the default -
  2384.     mov   al,0ffh                     ;  all data from cpu
  2385.     out   dx,al
  2386.     xor   ax,ax
  2387.     pop   ds                          ; restore data segment
  2388.     pop   di                          ; restore registers
  2389.     pop   si
  2390.     ret
  2391. xputmaskedvbmclipxy  endp
  2392.  
  2393. xscale PROC FAR DestX:WORD, DestY:WORD, DestWidth:WORD, DestHeight:WORD,\
  2394.                                 ScrnOffs : WORD, Bitmap:DWord
  2395.  
  2396. LOCAL   DecisionX:WORD, DecisionY:WORD, ClippedWidth:WORD, ClippedHeight:WORD,\
  2397.                 SourceWidth:WORD, SourceHeight:WORD, SourceOffset : Word,\
  2398.                 SourceWidth2 : Word, SourceHeight2 : word, ByteWidth : word,\
  2399.                 Plane : BYTE, DestWidth2 : word, DestHeight2 : word
  2400.  
  2401.                 push            ds
  2402.                 push    ds
  2403.                 lds                     si, Bitmap
  2404.                 xor     ah, ah
  2405.                 lodsb
  2406.                 mov     SourceWidth, ax
  2407.                 lodsb
  2408.                 mov     SourceHeight, ax
  2409.                 pop     ds
  2410.  
  2411.                 shl                     LeftClip, 2
  2412.                 shl     RightClip, 2
  2413.  
  2414.                 cmp     DestWidth, 2        ; If destination width is less than 2
  2415.                 jl      @@Done                ;     then don't draw it.
  2416.  
  2417.                 cmp     DestHeight, 2       ; If destination height is less than 2
  2418.                 jl      @@Done                ;     then don't draw it.
  2419.  
  2420.                 mov     ax, DestY           ; If it is completely below the
  2421.                 cmp     ax, BottomClip          ; lower clip bondry,
  2422.                 jg      @@Done                ;     then don't draw it.
  2423.  
  2424.                 add     ax, DestHeight      ; If it is above clip boundries
  2425.                 dec     ax                  ;     then don't draw it.
  2426.                 cmp     ax, TopClip
  2427.                 jl      @@Done
  2428.  
  2429.                 mov     ax, DestX           ; If it is to the right of the
  2430.                 cmp     ax, RightClip          ;     then don't draw it.
  2431.                 jg      @@Done
  2432.  
  2433.                 add     ax, DestWidth       ; If it is completely to the left
  2434.                 dec     ax                  ; of the left clip boundry,
  2435.                 cmp     ax, LeftClip          ;     then don't draw it.
  2436.                 jl      @@Done
  2437.  
  2438.                 mov     ax, DestWidth
  2439.                 mov     ClippedWidth, ax
  2440.  
  2441.                 shl     ax,1                ; Initialize the X decision var
  2442.                 neg     ax                  ; to be -2*DestWidth
  2443.                 mov     DecisionX, ax       ;
  2444.  
  2445.                 mov     ax, DestHeight      ; ClippedHeight is initially set to
  2446.                 mov     ClippedHeight, ax   ; the requested dest size.
  2447.  
  2448.                 shl     ax,1                ; Initialize the Y decision var
  2449.                 neg     ax                  ; to be -2*DestHeight
  2450.                 mov     DecisionY, ax       ;
  2451.  
  2452.                 mov                     SourceOffset, 0
  2453.  
  2454.                 movsx   eax, TopClip        ; If Y is below the top
  2455.                 mov     edx, eax            ; clipping boundry, then we don't
  2456.                 sub     dx, DestY           ; need to clip the top, so we can
  2457.                 js      @@NoTopClip         ; jump over the clipping stuff.
  2458.  
  2459.                 mov     DestY, ax           ; This block performs clipping on the
  2460.                 sub     ClippedHeight, dx   ; top of the bitmap.  I have heavily
  2461.                 movsx   ecx, SourceHeight   ; optimized this block to use only 4
  2462.                 imul    ecx, edx            ; 32-bit registers, so I'm not even
  2463.                 mov     eax, ecx            ; gonna try to explain what it's doing.
  2464.                 mov     edx, 0              ; But I can tell you what results from
  2465.                 movsx   ebx, DestHeight     ; this:  The DecisionY var is updated
  2466.                 idiv    ebx                 ; to start at the right clipped row.
  2467.                 movsx   edx, SourceWidth    ; Y is moved to the top clip
  2468.                 imul    edx, eax            ; boundry. ClippedHeight is lowered since
  2469.                 add     si, dx              ; we won't be drawing all the requested
  2470.                 imul    eax, ebx            ; rows.  SI is changed to point over
  2471.                 sub     ecx, eax            ; the bitmap data that is clipped off.
  2472.                 sub     ecx, ebx            ;
  2473.                 shl     ecx, 1              ;
  2474.                 mov     DecisionY, cx       ; <end of top clipping block >
  2475.  
  2476. @@NoTopClip:
  2477.                 mov     ax, DestY           ; If the bitmap doesn't extend over the
  2478.                 add     ax, ClippedHeight   ; bottom clipping boundry, then we
  2479.                 dec     ax                  ; don't need to clip the bottom, so we
  2480.                 cmp     ax, BottomClip      ; can jump over the bottom clip code.
  2481.                 jle     @@NoBottomClip      ;
  2482.  
  2483.                 mov     ax, BottomClip      ; Clip off the bottom by reducing the
  2484.                 sub     ax, DestY           ; ClippedHeight so that the bitmap won't
  2485.                 inc     ax                  ; extend over the lower clipping
  2486.                 mov     ClippedHeight, ax   ; boundry.
  2487.  
  2488. @@NoBottomClip:
  2489.                 movsx   eax, LeftClip       ; If X is to the left of the
  2490.                 mov     edx, eax            ; top clipping boundry, then we don't
  2491.                 sub     dx, DestX           ; need to clip the left, so we can
  2492.                 js      @@NoLeftClip        ; jump over the clipping stuff.
  2493.  
  2494.                 mov     DestX, ax           ; This block performs clipping on the
  2495.                 sub     ClippedWidth, dx    ; left of the bitmap.  I have heavily
  2496.                 movsx   ecx, SourceWidth    ; optimized this block to use only 4
  2497.                 imul    ecx, edx            ; 32-bit registers, so I'm not even
  2498.                 mov     eax, ecx            ; gonna try to explain what it's doing.
  2499.                 mov     edx, 0              ; But I can tell you what results from
  2500.                 movsx   ebx, DestWidth      ; this:  The DecisionX var is updated
  2501.                 idiv    ebx                 ; to start at the right clipped column.
  2502.                 add     SourceOffset, ax    ; X is moved to the left clip
  2503.                 imul    eax, ebx            ; boundry. ClippedWidth is reduced since
  2504.                 sub     ecx, eax            ; we won't be drawing all the requested
  2505.                 sub     ecx, ebx            ; cols.  SI is changed to point over
  2506.                 shl     ecx, 1              ; the bitmap data that is clipped off.
  2507.                 mov     DecisionX, cx       ; <end of left clipping block >
  2508.  
  2509. @@NoLeftClip:
  2510.                 mov     ax, DestX           ; If the bitmap doesn't extend over the
  2511.                 add     ax, ClippedWidth    ; right clipping boundry, then we
  2512.                 dec     ax                  ; don't need to clip the right, so we
  2513.                 cmp     ax, RightClip       ; can jump over the right clip code.
  2514.                 jle     @@NoClipRight       ;
  2515.  
  2516.                 mov     ax, RightClip       ; Clip off the right by reducing the
  2517.                 sub     ax, DestX           ; ClippedWidth so that the bitmap won't
  2518.                 inc     ax                  ; extend over the right clipping
  2519.                 mov     ClippedWidth, ax    ; boundry.
  2520.  
  2521.                 ;Calculate starting video address
  2522. @@NoClipRight:
  2523.                 mov                     ax, SourceWidth
  2524.                 shl     ax, 1
  2525.                 mov     SourceWidth2, ax
  2526.  
  2527.                 mov     ax, SourceHeight
  2528.                 shl     ax, 1
  2529.                 mov     SourceHeight2, ax
  2530.  
  2531.                 mov     ax, DestHeight
  2532.                 shl     ax, 1
  2533.                 mov     DestHeight2, ax
  2534.  
  2535.                 mov     ax, DestWidth
  2536.                 shl     ax, 1
  2537.                 mov     DestWidth2, ax
  2538.  
  2539.                 mov                     ax, ScrnLogicalByteWidth
  2540.                 mov     ByteWidth, ax
  2541.  
  2542.                 mov     ax, SCREENSEG
  2543.                 mov     es, ax
  2544.                 mov     ax, DestY
  2545.                 mov     bx, ScrnLogicalByteWidth
  2546.                 mul     bx
  2547.                 mov     di, ScrnOffs
  2548.                 add     di, ax
  2549.  
  2550.                 mov     cx, DestX
  2551.                 mov     dx, cx
  2552.                 shr     dx, 2
  2553.                 add     di, dx
  2554.  
  2555.                 lds     si, Bitmap
  2556.                 add     si, 2
  2557.                 add     si, SourceOffset
  2558.  
  2559.                 mov     dx, SCINDEX         ; Point the VGA Sequencer to the Map
  2560.                 mov     al, MAPMASK         ; Mask register, so that we only need
  2561.                 out     dx, al              ; to send out 1 byte per column.
  2562.  
  2563.                 inc     dx                  ; Move to the Sequencer's Data register.
  2564.                 and     cx, 3               ; Calculate the starting plane. This is
  2565.                 mov     al, 11h             ; just:
  2566.                 shl     al, cl              ; Plane =  (11h << (X AND 3))
  2567.                 mov     Plane, al
  2568.                 out     dx, al              ; Select the first plane.
  2569.  
  2570. @@RowLoop:
  2571.                 push    si                  ; Save the starting source index
  2572.                 push    di                  ; Save the starting dest index
  2573.  
  2574.                 mov     cx, ClippedHeight
  2575.                 mov     bx, DecisionY
  2576.                 mov     dx, ByteWidth
  2577.  
  2578.                 mov     al, ds:[si]
  2579.  
  2580. @@ColumnLoop:
  2581.                 mov     es:[di], al
  2582.                 add     di, dx
  2583.                 dec     cx
  2584.                 jz      @@DoneWithCol
  2585.                 add     bx, SourceHeight2
  2586.                 js      @@ColumnLoop
  2587.  
  2588. @@IncSourceRow:
  2589.                 add     si, SourceWidth
  2590.                 sub     bx, DestHeight2
  2591.                 jns     @@IncSourceRow
  2592.                 mov     al, ds:[si]
  2593.                 jmp     @@ColumnLoop
  2594.  
  2595. @@DoneWithCol:
  2596.                 pop     di
  2597.                 pop     si
  2598.  
  2599.                 rol     Plane, 1
  2600.                 adc     di, 0
  2601.                 mov     dx, SCINDEX
  2602.                 inc     dx
  2603.                 mov     al, Plane
  2604.                 out     dx, al
  2605.  
  2606.                 mov     ax, SourceWidth2
  2607.                 add     DecisionX, ax
  2608.                 js      @@NextCol
  2609. @@IncSourceCol:
  2610.                 inc     si
  2611.                 mov     ax, DestWidth2
  2612.                 sub     DecisionX, ax
  2613.                 jns     @@IncSourceCol
  2614. @@NextCol:
  2615.                 dec     ClippedWidth        ; If we're not at last column
  2616.                 jnz     @@RowLoop           ;    then do another column
  2617. @@Done:
  2618.                 pop     ds
  2619.                 shr                     LeftClip, 2
  2620.                 shr     RightClip, 2
  2621.                 ret                         ; We're done!
  2622.  
  2623. xscale     ENDP
  2624.  
  2625. xmaskedscale PROC FAR DestX:WORD, DestY:WORD, DestWidth:WORD, DestHeight:WORD,\
  2626.                                 ScrnOffs : WORD, Bitmap:DWord
  2627.  
  2628. LOCAL   DecisionX:WORD, DecisionY:WORD, ClippedWidth:WORD, ClippedHeight:WORD,\
  2629.                 SourceWidth:WORD, SourceHeight:WORD, SourceOffset : Word,\
  2630.                 SourceWidth2 : Word, SourceHeight2 : word, ByteWidth : word,\
  2631.                 Plane : BYTE, DestWidth2 : word, DestHeight2 : word
  2632.  
  2633.                 push            ds
  2634.                 push    ds
  2635.                 lds                     si, Bitmap
  2636.                 xor     ah, ah
  2637.                 lodsb
  2638.                 mov     SourceWidth, ax
  2639.                 lodsb
  2640.                 mov     SourceHeight, ax
  2641.                 pop     ds
  2642.  
  2643.                 shl                     LeftClip, 2
  2644.                 shl     RightClip, 2
  2645.  
  2646.                 cmp     DestWidth, 2        ; If destination width is less than 2
  2647.                 jl      @@Done                ;     then don't draw it.
  2648.  
  2649.                 cmp     DestHeight, 2       ; If destination height is less than 2
  2650.                 jl      @@Done                ;     then don't draw it.
  2651.  
  2652.                 mov     ax, DestY           ; If it is completely below the
  2653.                 cmp     ax, BottomClip          ; lower clip bondry,
  2654.                 jg      @@Done                ;     then don't draw it.
  2655.  
  2656.                 add     ax, DestHeight      ; If it is above clip boundries
  2657.                 dec     ax                  ;     then don't draw it.
  2658.                 cmp     ax, TopClip
  2659.                 jl      @@Done
  2660.  
  2661.                 mov     ax, DestX           ; If it is to the right of the
  2662.                 cmp     ax, RightClip          ;     then don't draw it.
  2663.                 jg      @@Done
  2664.  
  2665.                 add     ax, DestWidth       ; If it is completely to the left
  2666.                 dec     ax                  ; of the left clip boundry,
  2667.                 cmp     ax, LeftClip          ;     then don't draw it.
  2668.                 jl      @@Done
  2669.  
  2670.                 mov     ax, DestWidth
  2671.                 mov     ClippedWidth, ax
  2672.  
  2673.                 shl     ax,1                ; Initialize the X decision var
  2674.                 neg     ax                  ; to be -2*DestWidth
  2675.                 mov     DecisionX, ax       ;
  2676.  
  2677.                 mov     ax, DestHeight      ; ClippedHeight is initially set to
  2678.                 mov     ClippedHeight, ax   ; the requested dest size.
  2679.  
  2680.                 shl     ax,1                ; Initialize the Y decision var
  2681.                 neg     ax                  ; to be -2*DestHeight
  2682.                 mov     DecisionY, ax       ;
  2683.  
  2684.                 mov                     SourceOffset, 0
  2685.  
  2686.                 movsx   eax, TopClip        ; If Y is below the top
  2687.                 mov     edx, eax            ; clipping boundry, then we don't
  2688.                 sub     dx, DestY           ; need to clip the top, so we can
  2689.                 js      @@NoTopClip         ; jump over the clipping stuff.
  2690.  
  2691.                 mov     DestY, ax           ; This block performs clipping on the
  2692.                 sub     ClippedHeight, dx   ; top of the bitmap.  I have heavily
  2693.                 movsx   ecx, SourceHeight   ; optimized this block to use only 4
  2694.                 imul    ecx, edx            ; 32-bit registers, so I'm not even
  2695.                 mov     eax, ecx            ; gonna try to explain what it's doing.
  2696.                 mov     edx, 0              ; But I can tell you what results from
  2697.                 movsx   ebx, DestHeight     ; this:  The DecisionY var is updated
  2698.                 idiv    ebx                 ; to start at the right clipped row.
  2699.                 movsx   edx, SourceWidth    ; Y is moved to the top clip
  2700.                 imul    edx, eax            ; boundry. ClippedHeight is lowered since
  2701.                 add     si, dx              ; we won't be drawing all the requested
  2702.                 imul    eax, ebx            ; rows.  SI is changed to point over
  2703.                 sub     ecx, eax            ; the bitmap data that is clipped off.
  2704.                 sub     ecx, ebx            ;
  2705.                 shl     ecx, 1              ;
  2706.                 mov     DecisionY, cx       ; <end of top clipping block >
  2707.  
  2708. @@NoTopClip:
  2709.                 mov     ax, DestY           ; If the bitmap doesn't extend over the
  2710.                 add     ax, ClippedHeight   ; bottom clipping boundry, then we
  2711.                 dec     ax                  ; don't need to clip the bottom, so we
  2712.                 cmp     ax, BottomClip      ; can jump over the bottom clip code.
  2713.                 jle     @@NoBottomClip      ;
  2714.  
  2715.                 mov     ax, BottomClip      ; Clip off the bottom by reducing the
  2716.                 sub     ax, DestY           ; ClippedHeight so that the bitmap won't
  2717.                 inc     ax                  ; extend over the lower clipping
  2718.                 mov     ClippedHeight, ax   ; boundry.
  2719.  
  2720. @@NoBottomClip:
  2721.                 movsx   eax, LeftClip       ; If X is to the left of the
  2722.                 mov     edx, eax            ; top clipping boundry, then we don't
  2723.                 sub     dx, DestX           ; need to clip the left, so we can
  2724.                 js      @@NoLeftClip        ; jump over the clipping stuff.
  2725.  
  2726.                 mov     DestX, ax           ; This block performs clipping on the
  2727.                 sub     ClippedWidth, dx    ; left of the bitmap.  I have heavily
  2728.                 movsx   ecx, SourceWidth    ; optimized this block to use only 4
  2729.                 imul    ecx, edx            ; 32-bit registers, so I'm not even
  2730.                 mov     eax, ecx            ; gonna try to explain what it's doing.
  2731.                 mov     edx, 0              ; But I can tell you what results from
  2732.                 movsx   ebx, DestWidth      ; this:  The DecisionX var is updated
  2733.                 idiv    ebx                 ; to start at the right clipped column.
  2734.                 add     SourceOffset, ax    ; X is moved to the left clip
  2735.                 imul    eax, ebx            ; boundry. ClippedWidth is reduced since
  2736.                 sub     ecx, eax            ; we won't be drawing all the requested
  2737.                 sub     ecx, ebx            ; cols.  SI is changed to point over
  2738.                 shl     ecx, 1              ; the bitmap data that is clipped off.
  2739.                 mov     DecisionX, cx       ; <end of left clipping block >
  2740.  
  2741. @@NoLeftClip:
  2742.                 mov     ax, DestX           ; If the bitmap doesn't extend over the
  2743.                 add     ax, ClippedWidth    ; right clipping boundry, then we
  2744.                 dec     ax                  ; don't need to clip the right, so we
  2745.                 cmp     ax, RightClip       ; can jump over the right clip code.
  2746.                 jle     @@NoClipRight       ;
  2747.  
  2748.                 mov     ax, RightClip       ; Clip off the right by reducing the
  2749.                 sub     ax, DestX           ; ClippedWidth so that the bitmap won't
  2750.                 inc     ax                  ; extend over the right clipping
  2751.                 mov     ClippedWidth, ax    ; boundry.
  2752.  
  2753.                 ;Calculate starting video address
  2754. @@NoClipRight:
  2755.                 mov                     ax, SourceWidth
  2756.                 shl     ax, 1
  2757.                 mov     SourceWidth2, ax
  2758.  
  2759.                 mov     ax, SourceHeight
  2760.                 shl     ax, 1
  2761.                 mov     SourceHeight2, ax
  2762.  
  2763.                 mov     ax, DestHeight
  2764.                 shl     ax, 1
  2765.                 mov     DestHeight2, ax
  2766.  
  2767.                 mov     ax, DestWidth
  2768.                 shl     ax, 1
  2769.                 mov     DestWidth2, ax
  2770.  
  2771.                 mov                     ax, ScrnLogicalByteWidth
  2772.                 mov     ByteWidth, ax
  2773.  
  2774.                 mov     ax, SCREENSEG
  2775.                 mov     es, ax
  2776.                 mov     ax, DestY
  2777.                 mov     bx, ScrnLogicalByteWidth
  2778.                 mul     bx
  2779.                 mov     di, ScrnOffs
  2780.                 add     di, ax
  2781.  
  2782.                 mov     cx, DestX
  2783.                 mov     dx, cx
  2784.                 shr     dx, 2
  2785.                 add     di, dx
  2786.  
  2787.                 lds     si, Bitmap
  2788.                 add     si, 2
  2789.                 add     si, SourceOffset
  2790.  
  2791.                 mov     dx, SCINDEX         ; Point the VGA Sequencer to the Map
  2792.                 mov     al, MAPMASK         ; Mask register, so that we only need
  2793.                 out     dx, al              ; to send out 1 byte per column.
  2794.  
  2795.                 inc     dx                  ; Move to the Sequencer's Data register.
  2796.                 and     cx, 3               ; Calculate the starting plane. This is
  2797.                 mov     al, 11h             ; just:
  2798.                 shl     al, cl              ; Plane =  (11h << (X AND 3))
  2799.                 mov     Plane, al
  2800.                 out     dx, al              ; Select the first plane.
  2801.  
  2802. @@RowLoop:
  2803.                 push    si                  ; Save the starting source index
  2804.                 push    di                  ; Save the starting dest index
  2805.  
  2806.                 mov     cx, ClippedHeight
  2807.                 mov     bx, DecisionY
  2808.                 mov     dx, ByteWidth
  2809.  
  2810.                 mov     al, ds:[si]
  2811.  
  2812. @@ColumnLoop:
  2813.                 or      al, al
  2814.                 jz      @@DontDraw
  2815.                 mov     es:[di], al
  2816. @@DontDraw:
  2817.                 add     di, dx
  2818.                 dec     cx
  2819.                 jz      @@DoneWithCol
  2820.                 add     bx, SourceHeight2
  2821.                 js      @@ColumnLoop
  2822.  
  2823. @@IncSourceRow:
  2824.                 add     si, SourceWidth
  2825.                 sub     bx, DestHeight2
  2826.                 jns     @@IncSourceRow
  2827.                 mov     al, ds:[si]
  2828.                 jmp     @@ColumnLoop
  2829.  
  2830. @@DoneWithCol:
  2831.                 pop     di
  2832.                 pop     si
  2833.  
  2834.                 rol     Plane, 1
  2835.                 adc     di, 0
  2836.                 mov     dx, SCINDEX
  2837.                 inc     dx
  2838.                 mov     al, Plane
  2839.                 out     dx, al
  2840.  
  2841.                 mov     ax, SourceWidth2
  2842.                 add     DecisionX, ax
  2843.                 js      @@NextCol
  2844. @@IncSourceCol:
  2845.                 inc     si
  2846.                 mov     ax, DestWidth2
  2847.                 sub     DecisionX, ax
  2848.                 jns     @@IncSourceCol
  2849. @@NextCol:
  2850.                 dec     ClippedWidth        ; If we're not at last column
  2851.                 jnz     @@RowLoop           ;    then do another column
  2852. @@Done:
  2853.                 pop     ds
  2854.                 shr                     LeftClip, 2
  2855.                 shr     RightClip, 2
  2856.                 ret                         ; We're done!
  2857.  
  2858. xmaskedscale     ENDP
  2859.  
  2860. end
  2861.